Оптимизация сложного SQL: 5 мест, где план обычно теряет время и память
Коллеги, давайте разберем план выполнения. Сложный запрос редко «тормозит вообще» — обычно у него есть 1–2 узких места: лишний проход по большим данным, плохая селективность фильтра или неудачный join. Сначала смотрим не на текст, а на фактический план: где растут rows, где идет sort/hash spill, где появляется nested loop на миллионы строк.
— Упростите фильтры до sargable-формы: без функций по колонке, без неявных преобразований типов.
— Проверьте join-порядок и кардинальность: ошибка в оценке строк часто ломает весь план.
— Уберите лишние CTE/подзапросы, если они заставляют оптимизатор материализовать промежуточный результат.
— Отдельно смотрите на DISTINCT, GROUP BY, ORDER BY: часто именно они съедают память и I/O.
— Индекс полезен только если он совпадает с предикатом и не превращает запись в медленный аттракцион.
Схема простая, но дьявол кроется в статистике. Если статистика устарела или данные сильно перекошены, оптимизатор выбирает красивый на бумаге, но дорогой в реальности путь. Посмотрим, что тут с I/O в реальности: если чтение идет массово, а фильтр отбрасывает почти все строки, индекс или переписанный predicate дадут больше, чем «еще один hint».
В продакшене так лучше не делать, и вот почему: сначала лечим запрос, потом уже спорим с индексами и настройками памяти. Золотое правило: сначала мониторинг, потом индексы.
Оптимизация производительности баз
@database_performance_tuning_arb
Оптимизация сложного SQL: 5 мест, где план обычно теряет время и память
Этот пост опубликован в Telegram-канале Оптимизация производительности баз. Подписаться можно по ссылке: @database_performance_tuning_arb.