Каковы причины и действия, если планировщик запросов (optimizer) не использует индекс?

«Каковы причины и действия, если планировщик запросов (optimizer) не использует индекс?» — вопрос из категории Базы данных, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Основные причины и диагностика:

  1. Полное сканирование выгоднее:

    • Для маленьких таблиц или условий с низкой селективностью (>15-30% строк) сканирование таблицы (TABLE SCAN) часто быстрее. Проверить можно через EXPLAIN ANALYZE:
      EXPLAIN ANALYZE SELECT * FROM users WHERE status = 'inactive';
  2. Несоответствие типов данных:

    • Неявное преобразование типов, например, сравнение строкового поля с числом (WHERE string_column = 123), блокирует использование индекса.
  3. Использование функций или выражений:

    • Индекс не используется, если столбец участвует в выражении: WHERE UPPER(name) = 'JOHN' или WHERE price + tax > 100. Решение: переписать запрос или создать функциональный индекс.
  4. Устаревшая статистика:

    • Планировщик принимает решение на основе статистики. Если она устарела, решение может быть неоптимальным. Обновить: ANALYZE TABLE table_name; (или UPDATE STATISTICS).
  5. Проблема с составным индексом:

    • Составной индекс (A, B, C) не будет использован для условия только по B или C. Порядок столбцов в индексе должен соответствовать условиям в WHERE и ORDER BY.
  6. Параметризованные запросы и «проблема параметра»:

    • При использовании подготовленных выражений (prepared statements) с параметрами планировщик может использовать усредненную статистику. В некоторых СУБД помогает OPTION (RECOMPILE) или использование литералов для отладки.