<b>Сложный SQL тормозит не из-за “плохого сервера”, а из-за неудачного плана</b>
Коллеги, давайте разберем план выполнения. У сложных запросов почти всегда ломается одно из трёх: фильтрация слишком поздняя, JOIN раздувает промежуточный набор, сортировка или группировка съедает память и уходит в temp. Сначала смотрим не на текст SQL, а на фактический план: где больше всего строк, где есть Seq Scan, nested loop на больших объёмах и лишние пересчёты.
Дальше работаем по порядку:
— проталкиваем фильтры как можно раньше;
— убираем функции с колонок в WHERE и JOIN, если нужен индекс;
— проверяем, не тащит ли CTE/подзапрос лишние строки;
— заменяем SELECT * на нужные поля, особенно перед JOIN и сортировкой;
— пересматриваем порядок соединений, если одна таблица маленькая, а другая раздута.
Золотое правило: сначала мониторинг, потом индексы.
Если запрос агрегирует данные, ищите место, где можно сократить набор до JOIN. Иногда выгоднее сначала отобрать ключи, потом присоединять детали. Если есть OR по разным полям, план часто деградирует в обход индексов — такие условия лучше дробить на UNION ALL, но только если это не ломает семантику. И да, индексы наугад не спасают, если статистика врёт или условие не sargable.
Перед выкладкой в продакшен прогоняйте запрос на реалистичном объёме и смотрите I/O в реальности, а не только время в IDE. Схема простая, но дьявол кроется в статистике: сначала убираем лишнюю работу из плана, и только потом думаем про новые индексы.
Оптимизация производительности баз
@database_performance_tuning_arb
<b>Сложный SQL тормозит не из-за “плохого сервера”, а из-за неудачного плана</b>
Этот пост опубликован в Telegram-канале Оптимизация производительности баз. Подписаться можно по ссылке: @database_performance_tuning_arb.