← Назад к вопросам

Какие данные не стоит индексировать?

1.7 Middle🔥 172 комментариев
#Базы данных

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Данные, которые не стоит индексировать в базах данных

Индексы — это мощный инструмент для ускорения операций чтения в базах данных, но их нерациональное использование может привести к серьезным проблемам с производительностью, увеличением размера базы и сложностью поддержки. Вот ключевые типы данных и ситуации, когда создание индексов не рекомендуется или требует особой осторожности.

1. Столбцы с низкой селективностью (низкой уникальностью)

Селективность — это мера уникальности значений в столбце. Индексы по столбцам с малым количеством уникальных значений (например, пол, статус заказа, флаг активности) часто неэффективны. Оптимизатор запросов может проигнорировать такой индекс, так как он не сужает выборку значительно.

-- Плохой кандидат для индекса (всего 2-3 уникальных значения)
CREATE INDEX idx_gender ON users(gender); -- 'M', 'F', NULL

-- Вместо этого, рассмотреть частичный индекс, если часто фильтруем по конкретному значению
CREATE INDEX idx_active_users ON users(id) WHERE is_active = true;

2. Часто изменяемые данные (высокая волатильность)

Каждое изменение (INSERT, UPDATE, DELETE) в индексируемом столбце требует перестройки соответствующих фрагментов индекса. Это создает дополнительную нагрузку на запись.

  • Примеры: столбцы-счетчики, временные метки, которые обновляются часто, поля с сессионными данными.
  • Баланс: если такие столбцы редко используются в WHERE, JOIN или ORDER BY, индекс принесет больше вреда, чем пользы.

3. Большие объекты (BLOBs, TEXT) и длинные строки

Индексирование всего содержимого полей типа TEXT или BLOB технически возможно не во всех СУБД и почти всегда нецелесообразно из-за огромного размера индекса. Вместо этого используют:

  • Частичные индексы на префиксах (первые N символов).
  • Генерируемые столбцы с хэшем (например, MD5) от содержимого и индекс по этому хэшу.
  • Полнотекстовые индексы для поиска по словам внутри текста, а не обычные B-деревья.
-- Плохо: попытка проиндексировать весь текст
CREATE INDEX idx_content ON articles(full_text);

-- Лучше: индекс по префиксу или хэшу
CREATE INDEX idx_content_prefix ON articles(full_text(100)); -- Первые 100 символов
ALTER TABLE articles ADD COLUMN content_hash CHAR(32) AS (MD5(full_text));
CREATE INDEX idx_content_hash ON articles(content_hash);

4. Столбцы, которые уже являются частью другого (составного) индекса

Создание отдельного индекса на столбец, который является первым в существующем составном индексе, обычно избыточно. Составной индекс (category_id, created_at) уже может эффективно использоваться для запросов только по category_id.

  • Исключение: иногда отдельный индекс на второй или третий столбец составного индекса может быть полезен для совсем других запросов, но это требует анализа.

5. Таблицы с небольшим объемом данных ("малые таблицы")

Для таблиц, которые помещаются в память (например, справочники типов документов на 100 записей), полное сканирование (FULL SCAN) часто выполняется быстрее, чем поиск по индексу с дополнительным переходом к данным. Накладные расходы на обслуживание индекса не окупаются.

6. Столбцы, которые не используются в условиях поиска, сортировки или соединения

Золотое правило: индекс должен создаваться под конкретную рабочую нагрузку (workload). Не стоит индексировать столбец "на всякий случай". Анализируйте медленные запросы (slow query log) и EXPLAIN-планы.

  • Столбцы, используемые только в SELECT (выводятся, но не фильтруются).
  • Столбцы в условиях, которые не могут использовать индекс (например, из-за применения функций WHERE UPPER(name) = '...', если нет функционального индекса).

7. Данные с особым распределением: NULL-значения

Если столбец содержит очень большое процентное соотношение NULL-значений (например, >80%), и типичные запросы ищут WHERE column IS NOT NULL, то стандартный индекс может быть неэффективен. В некоторых СУБД (например, PostgreSQL) можно создать частичный индекс, исключающий NULL.

-- Эффективный индекс только для не-NULL значений
CREATE INDEX idx_email ON users(email) WHERE email IS NOT NULL;

8. Чрезмерное индексирование (овер-индексинг) в целом

Каждый дополнительный индекс:

  • Замедляет операции записи (INSERT, UPDATE, DELETE).
  • Увеличивает потребление дискового пространства.
  • Усложняет работу оптимизатора (больше вариантов для выбора).
  • Увеличивает время обслуживания (перестройка индексов, бэкапы).

Стратегия: Приоритизируйте индексы по:

  1. Высокоселективным столбцам, часто используемым в WHERE.
  2. Ключам соединения (JOIN) для часто выполняемых запросов.
  3. Столбцам в ORDER BY, особенно в сочетании с фильтрацией.

Заключение

Решение об индексации — это всегда компромисс между скоростью чтения и скоростью записи, а также между производительностью и ресурсами. Не существует "абсолютно плохих" данных для индексации — все зависит от конкретной схемы данных, паттернов доступа и объема. Регулярный мониторинг (использование индексов через pg_stat_user_indexes в PostgreSQL или sys.dm_db_index_usage_stats в SQL Server) и профилирование запросов — обязательные практики для поддержания оптимальной индексации.