В каком случае при наличии индекса будет полное сканирование таблицы (full scan)?

«В каком случае при наличии индекса будет полное сканирование таблицы (full scan)?» — вопрос из категории SQL и базы данных, который задают на 33% собеседований Data Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Оптимизатор СУБД может выбрать полное сканирование таблицы (FULL TABLE SCAN) вместо использования индекса в следующих основных случаях:

  1. Низкая селективность условия: Если условие WHERE охватывает большую часть таблицы (например, >15-20% строк). Сканирование по индексу с последующими обращениями к таблице (TABLE ACCESS BY INDEX ROWID) становится дороже, чем прямое последовательное чтение.

    -- Индекс по is_active вряд ли будет использован, если 90% строк active
    SELECT * FROM users WHERE is_active = TRUE;
  2. Отсутствие подходящего префикса индекса: Для составного индекса (A, B) запрос с фильтром только по B не сможет его использовать эффективно.

  3. Использование функций или модификаторов столбца: Индекс по created_at не будет использован, если применить к нему функцию.

    -- Не использует индекс по created_at
    SELECT * FROM logs WHERE DATE(created_at) = '2023-10-01';
    -- Решение: создать функциональный индекс или переписать запрос
    SELECT * FROM logs WHERE created_at >= '2023-10-01' AND created_at < '2023-10-02';
  4. Неактуальная статистика: Если статистика по таблице устарела, оптимизатор может ошибиться в оценке стоимости.

  5. Подсказка оптимизатору или маленькая таблица: Для очень маленьких таблиц сканирование всегда дешевле. Также можно явно указать /*+ FULL(table_name) */.

Как проверить? Используйте EXPLAIN (или EXPLAIN ANALYZE):

EXPLAIN ANALYZE
SELECT * FROM large_table WHERE low_selectivity_column = 'common_value';
-- В плане выполнения будет видно "Seq Scan" вместо "Index Scan"