Как определить, что индекс используется в SQL-запросе
Что проверяют
Умеете ли вы читать план запроса, а не гадать. Это ежедневный навык при разборе медленных запросов.
Как отвечать
Единственный надёжный способ это посмотреть план:
explain (analyze, buffers) select * from users where email = $1;EXPLAIN показывает предполагаемый план, добавление ANALYZE выполняет запрос и показывает фактическое время и число строк, а BUFFERS сколько страниц прочитано.
Что смотреть в выводе:
- тип доступа:
Index ScanилиIndex Only Scanозначает, что индекс используется,Bitmap Index Scanтоже, аSeq Scanэто полный проход по таблице; - расхождение оценок: если планировщик ждал сто строк, а вернулось сто тысяч, значит статистика устарела, и стоит выполнить
ANALYZEдля таблицы; - фильтр после чтения: строка
Filterс большим числом отброшенных строк показывает, что индекс отобрал слишком широко; - время по узлам: видно, где именно уходит время.
Дополнительно полезно назвать:
pg_stat_user_indexesпоказывает, сколько раз индекс использовался вообще. Индекс с нулём обращений это кандидат на удаление, потому что он замедляет запись;pg_stat_statementsнаходит самые дорогие запросы, с них и начинают.
И причины, по которым индекс не берётся, даже когда он есть: функция или приведение типа над колонкой, условие не по левому префиксу составного индекса, слишком большая доля таблицы в выборке (тогда полный проход дешевле), устаревшая статистика, несовпадение типов параметра и колонки.
Где спотыкаются
Проверяют на пустой тестовой базе, где планировщик всегда выбирает полный проход.
Смотрят только EXPLAIN без ANALYZE и делают выводы по оценкам, а не по фактам.
Считают отсутствие индекса причиной, хотя запрос отбирает половину таблицы, и полный проход тут правильный выбор.