Оценка производительности SQL
Оптимизация начинается с измеримого симптома, а не с переписывания синтаксиса. Один и тот же запрос зависит от параметров, распределения данных, кэша, конкуренции и версии СУБД.
Порядок расследования
- Зафиксировать запрос, параметры и требуемый результат.
- Измерить latency, частоту, число возвращаемых строк и влияние на систему.
- Получить фактический план (
EXPLAIN ANALYZEили аналог) безопасным способом. - Сравнить estimated rows с actual rows.
- Найти основную стоимость: scan, join, sort, aggregate, temp spill, network.
- Проверить статистику и существующие индексы.
- Сделать одно изменение и повторить измерение.
Warning
Команда с фактическим выполнением действительно выполняет запрос. Для изменяющего DML нужен безопасный стенд или осознанная транзакция с rollback; даже она может оставить побочные эффекты вне БД.
Что читать в плане
Seq/Table ScanилиIndex Scan/Seek;- алгоритм соединения: nested loop, hash join, merge join;
- порядок соединений;
- оцененное и фактическое число строк;
- количество циклов узла;
- сортировка и выход за доступную память;
- чтение страниц/буферов и временных данных;
- время планирования и исполнения.
Большое расхождение estimated rows и actual rows часто указывает на устаревшую статистику, коррелированные столбцы, неравномерное распределение или параметр-чувствительный план.
Что измерять кроме latency
- throughput и p95/p99;
- CPU, logical/physical reads, temporary I/O;
- ожидания блокировок;
- количество соединений и round trips;
- размер результата;
- частоту запроса: 2 мс × миллион вызовов важнее единичных 200 мс.
Частые причины
- N+1 запросов;
- отсутствующий или неподходящий индекс;
- чтение лишних строк/столбцов;
- неявное приведение типов;
- размножение строк до агрегации;
- пагинация с большим
OFFSET; - lock contention;
- неверная оценка селективности.
Проверка результата
Оптимизированный запрос должен быть семантически эквивалентен: сравнивают не только скорость, но и строки, NULL, дубликаты, порядок и поведение при конкуренции.
Связано: Индексы SQL, Селективность SQL, Что лучше подзапросы или JOIN, Кейс фильтр поверх UNION.
Вопросы
Почему одного EXPLAIN мало? Он показывает оценки; фактическое выполнение выявляет реальные строки, циклы и время.
Что означает сильное расхождение estimate/actual? Оптимизатор неправильно оценил кардинальность, поэтому мог выбрать неудачный план.
Всегда ли index scan быстрее seq scan? Нет; при чтении большой доли таблицы последовательный проход дешевле.
Почему p99 важен? Среднее скрывает хвост задержек, который видят пользователи и очереди.
Как доказать улучшение? Сравнить воспроизводимые замеры и корректность до/после на репрезентативных данных.