Почему PostgreSQL может отказаться делать поиск по индексу на поле?

«Почему PostgreSQL может отказаться делать поиск по индексу на поле?» — вопрос из категории Базы данных, который задают на 26% собеседований Node.js Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Планировщик запросов PostgreSQL может принять решение не использовать индекс, если полное сканирование таблицы (sequential scan) оценивается как более эффективное. Основные причины:

  1. Низкая селективность индекса: Если условие отбирает большую часть таблицы (например, WHERE active = true, где true у 90% строк), сканирование всей таблицы может быть быстрее из-за накладных расходов на случайный доступ к индексу и затем к таблице.
  2. Несоответствие типов данных или использование функций:

    -- Индекс по текстовому полю email не будет использован из-за неявного приведения
    SELECT * FROM users WHERE email = 123;
    
    -- Индекс по timestamp полю created_at не будет использован из-за функции
    SELECT * FROM orders WHERE DATE(created_at) = '2023-01-01';
  3. Недостаточный объем данных: Для очень маленьких таблиц (часто менее ~1000 строк) накладные расходы на использование индекса превышают выгоду.
  4. Устаревшая статистика: PostgreSQL использует статистику для оценки селективности. Если статистика устарела (ANALYZE не запускался давно), планировщик может ошибиться в выборе плана.
  5. Отсутствие подходящего индекса: Частичный индекс (CREATE INDEX ... WHERE ...) не будет использован, если условие запроса не покрывается его предикатом.

Как проверить? Используйте EXPLAIN или EXPLAIN ANALYZE перед запросом, чтобы увидеть выбранный план выполнения.