Совет дня №19
Чтобы узнать план запроса, предварите его командой EXPLAIN:
explain select * from applications;
Seq Scan on applications
(cost=0.00..359524.33 rows=965633 width=1745)
Эта команда НЕ выполнит запрос, а только вернет его план и приблизительные оценки.
План представляет дерево узлов; вложенность определяется пробелами слева. План читают от вложенных узлов к корню. Графические программы вроде PGAdmin показывают его в виде графа. У каждого узла как минимум три характеристики: стоимость (cost), число записей (rows) и средняя длина строки (width).
Стоимость (cost) – это условные попугаи, в которых измеряется каждая операция. С помощью глобальных настроек можно задать свою стоимость некоторым операциям, но обычно это ни к чему. Кроме того, стоимость можно задать функциям при их объявлении.
Число записей (rows) – ожидаемое число записей, которые произведет узел. Для них рассчитана средняя длина в байтах. Эти числа берутся из статистики и могут быть неточны.
Стоимость выражается двумя цифрами: X..Y. Первая цифра – столько усилий уйдет на то, чтобы произвести первую запись. Вторая – последнюю, то есть все остальное.
Зачем две цифры? Дело в том, что даже когда запрос производит много записей, важно знать, сколько усилий требует предварительная работа. Например, у обхода большой таблицы первый кост маленький, а второй – большой. Это нормально, потому что записи передаются следующему узлу без задержки. Если же добавить группировку, то следующий узел не получит данные, пока не выполнится группировка. Из-за этого первый кост будет большим. В идеале нужно держать его маленьким, чтобы клиент сразу начал получать строки.
У команды explain много параметров, чтобы собрать дополнительные метрики
узлов. Например, время в секундах, число прочитанных страниц, попадание в
буферный кэш. Самый важный параметр называется ANALYZE. С ним запрос будет
выполнен, и метрики будут реальными, а не оценочными.
Модуль auto_explain автоматически логирует план запросов, которые выполнялись
дольше порога, например одной секунды. Иногда его включают на проде.
Читать план тяжело, этот навык приходит с годами. Вы должны точно понимать, какую информацию ищете и почему ее там нет. В простом случае вас интересует, использовался ли индекс. Вы запускаете explain analyze и смотрите, был ли узел с типом “index scan”.
Узел “index only scan” означает, что данные получены из индекса без обращения к таблице. Это самый жир, лучше которого ничего не бывает. Узел “bitmap index scan” означает построение битовой карты, где каждый бит — номер блока. Такой обход используется для совмещения нескольких индексов, и он тоже хорош.
Узел “full seq scan” означает полный обход таблицы. Это нормально, если таблица мала или нужна ее большая часть. Если вы рассчитывали на индекс, это повод пересмотреть его.
Нашли ошибку? Выделите мышкой и нажмите Ctrl/⌘+Enter