Gymterview
senior

Когда полное сканирование набора данных выгоднее доступа по индексу?

Полное сканирование (Sequential Scan) выгоднее доступа по индексу (Index Scan), когда суммарная стоимость одноблочных чтений через индекс превышает стоимость многоблочного последовательного чтения всей таблицы.

Механика сравнения

Характеристика Полное сканирование Доступ по индексу
Тип чтения Многоблочное (sequential I/O) Одноблочное (random I/O)
Скорость одного чтения Высокая (последовательно) Низкая (случайные позиции)
Количество чтений Все блоки таблицы Блоки индекса + блоки данных
Эффективность Постоянная Зависит от селективности и кластеризации

Когда полное сканирование выгоднее

  • Низкая селективность предиката — запрос возвращает значительную долю таблицы (ориентир: более 5-15% строк, зависит от СУБД)
  • Слабая кластеризация данных — строки, отобранные индексом, разбросаны по разным страницам диска
  • Маленькая таблица — целиком помещается в несколько блоков
  • Нет подходящего индекса — запрос по неиндексированному столбцу
  • Покрывающий индекс недоступен — после Index Scan нужен дополнительный переход к таблице (Heap Fetch)

Как оптимизатор принимает решение

Оптимизатор СУБД оценивает стоимость каждого плана на основе:

  • Статистики таблиц (количество строк, распределение значений)
  • Фактора кластеризации (correlation в PostgreSQL)
  • Стоимости sequential I/O vs random I/O
  • Размера буферного пула (shared_buffers)
Пример
-- PostgreSQL: посмотреть план запроса
EXPLAIN ANALYZE SELECT * FROM orders WHERE status = 'active';

-- Если оптимизатор выбирает Seq Scan, значит он считает его дешевле

Практический пример

Таблица orders: 1 000 000 строк, 90% имеют status = 'completed'.

Пример
-- Индекс НЕ используется (90% строк — полное сканирование дешевле)
SELECT * FROM orders WHERE status = 'completed';

-- Индекс используется (2% строк — высокая селективность)
SELECT * FROM orders WHERE status = 'refunded';

На собеседовании: интервьюер проверяет понимание работы оптимизатора. Ключевая мысль: random I/O дороже sequential I/O, и при большой доле возвращаемых строк накопленная стоимость одноблочных чтений превышает стоимость одного последовательного прохода. Частая ошибка — не упомянуть фактор кластеризации.