разработка
•
•
198 просмотров
Я обещал пояснить утренний вайб
Увеличить
Я обещал пояснить утренний вайб 🤔
Вот вам история, детишки о том, как я продолбался с N+1 запросами и не замечал этого 😳
Писал несколько ночей подряд, так что ногами не пинайте, но получилось так, что всё вроде работает. А потом открываю АПИ через Postman — и он грузится 11 секунд.
И данных-то кот наплакал.
Открываю MenuService и вижу красивое:
Для КАЖДОГО товара — отдельный SQL-запрос за размерами. Ну,кайф?
menuItems. stream()
.collect(Collectors.toMap(
MenuItem::getId,
menuItemSizeRepository::findByMenuItemId));
Т.е. то, что называют N+1.
Вместо того чтобы одним SELECT ... WHERE id IN (...) загрузить все размеры разом, для каждого товара делал отдельный поход в базу.
И это ещё, сука, не всё — то же самое для модификаторов 😒
Причём модификаторы — это N+1 в квадрате: сначала для каждой категории запрос за списком ID модификаторов, потом для каждого ID — ещё запрос за самим модификатором.
Итого при 50 позициях в меню: 1 запрос за товарами + 50 за размерами + 8 за связями категорий + 24 за модификаторами = 83 SQL-запроса на один API-эндпоинт.
И этот паттерн был в 6 методах. Переделал на batch-метод
findByMenuItemIds(List<String>) с IN(...)
И 83 запроса превратились в 4 😊
Но вот в чём ирония: после деплоя фикса почти не стало лучше 😩
А потом оказалось, что у провайдера были проблемы с каналом 😡
Но в итоге, это толкнуло меня к рефакторингу и вместо 11 секунд — меньше секунды.
З.Ы. Гоните меня, насмехайтесь надо мной 😅
Вот вам история, детишки о том, как я продолбался с N+1 запросами и не замечал этого 😳
Писал несколько ночей подряд, так что ногами не пинайте, но получилось так, что всё вроде работает. А потом открываю АПИ через Postman — и он грузится 11 секунд.
И данных-то кот наплакал.
Открываю MenuService и вижу красивое:
Для КАЖДОГО товара — отдельный SQL-запрос за размерами. Ну,кайф?
menuItems. stream()
.collect(Collectors.toMap(
MenuItem::getId,
menuItemSizeRepository::findByMenuItemId));
Т.е. то, что называют N+1.
Вместо того чтобы одним SELECT ... WHERE id IN (...) загрузить все размеры разом, для каждого товара делал отдельный поход в базу.
И это ещё, сука, не всё — то же самое для модификаторов 😒
Причём модификаторы — это N+1 в квадрате: сначала для каждой категории запрос за списком ID модификаторов, потом для каждого ID — ещё запрос за самим модификатором.
Итого при 50 позициях в меню: 1 запрос за товарами + 50 за размерами + 8 за связями категорий + 24 за модификаторами = 83 SQL-запроса на один API-эндпоинт.
И этот паттерн был в 6 методах. Переделал на batch-метод
findByMenuItemIds(List<String>) с IN(...)
И 83 запроса превратились в 4 😊
Но вот в чём ирония: после деплоя фикса почти не стало лучше 😩
А потом оказалось, что у провайдера были проблемы с каналом 😡
Но в итоге, это толкнуло меня к рефакторингу и вместо 11 секунд — меньше секунды.
З.Ы. Гоните меня, насмехайтесь надо мной 😅
#Разработка
#Рефакторинг
#СраныйПровайдер
Понравился пост?
Обсуди его в Telegram-канале!
Обсуждение
Комментарии доступны через Telegram. Для участия в обсуждении нужен аккаунт Telegram.
Поделиться: Telegram