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

Что такое кардинальность (cardinality) индекса?

2.7 Senior🔥 151 комментариев
#Базы данных и SQL

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

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

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

Что такое кардинальность индекса?

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

Проще говоря, кардинальность отвечает на вопрос: "Сколько уникальных значений содержится в этом индексе?". Высокая кардинальность означает, что значений много и они в значительной степени уникальны (например, первичный ключ id, email). Низкая кардинальность указывает на малое количество уникальных значений (например, столбец gender с значениями 'M'/'F', или status с несколькими вариантами).

Как считается кардинальность?

В реляционных СУБД кардинальность часто вычисляется как отношение количества уникальных значений в индексе к общему числу записей в таблице:

Кардинальность = (COUNT(DISTINCT column_value) / COUNT(*)) * 100%

На практике СУБД может использовать приблизительные статистики (например, при помощи выборки), которые обновляются периодически командой ANALYZE TABLE в MySQL или ANALYZE в PostgreSQL.

Практическое значение для оптимизатора запросов

Оптимизатор запросов использует статистику кардинальности, чтобы предсказать, сколько строк будет возвращено при использовании того или иного индекса. Это критически важно для выбора наиболее селективного (эффективного) индекса.

Пример на SQL:

Представим таблицу users:

CREATE TABLE users (
    id INT PRIMARY KEY,
    email VARCHAR(255) UNIQUE,
    country_code CHAR(2),
    created_at TIMESTAMP
);

CREATE INDEX idx_country ON users(country_code);
CREATE INDEX idx_created ON users(created_at);

Допустим, в таблице 1 000 000 записей.

  • Индекс id (PRIMARY KEY): Кардинальность ~1 000 000. Идеальная селективность — одна запись на одно значение.
  • Индекс email (UNIQUE): Кардинальность также ~1 000 000. Высокая селективность.
  • Индекс country_code: Если есть 50 стран, кардинальность ~50. Низкая селективность. Запрос WHERE country_code = 'US' может вернуть десятки тысяч строк.
  • Индекс created_at (TIMESTAMP): Кардинальность может быть высокой (если даты сильно разнятся), но часто значения группируются (много записей за один день).

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

Для запроса:

SELECT * FROM users WHERE country_code = 'US' AND created_at > '2023-01-01';

Оптимизатор проанализирует:

  1. Кардинальность idx_country: низкая. Фильтр country_code = 'US' отсеет, но останется много строк.
  2. Кардинальность idx_created: может быть выше в этом диапазоне. Фильтр по дате может быть более селективным.
  3. Возможность комбинированного индекса (country_code, created_at). Его кардинальность для префикса country_code низкая, но для полной пары (country_code, created_at) — очень высокая, что делает его идеальным для этого запроса.

Ключевые выводы и лучшие практики

  • Высокая кардинальность → Высокая селективность → Эффективный индекс. Индексы по первичным ключам, уникальным полям и колонкам с множеством уникальных значений (даты, хэши) используются в первую очередь.
  • Низкая кардинальность → Низкая селективность → Индекс часто игнорируется. Для условий с малым количеством вариантов (пол, тип) оптимизатор может предпочесть полный сканирование таблицы, если это быстрее, чем множество случайных чтений индекса с последующими обращениями к данным.
  • Статистики нужно обновлять. Если кардинальность в статистике не соответствует реальности (после массовых вставок/удалений), оптимизатор может выбрать плохой план выполнения. Регулярный ANALYZE TABLE обязателен.
  • Составные индексы (комposite indexes) — главный инструмент повышения эффективности. Правильный порядок колонок в таком индексе (от более селективной к менее селективной или согласно принципу "равенство → диапазон → сортировка") кардинально меняет картину. Например, для запроса выше индекс (country_code, created_at) будет иметь намного более высокую кардинальность для условия WHERE country_code = 'US' AND created_at > ..., чем каждый индекс по отдельности.
  • Кардинальность ≠ Селективность, но они тесно связаны. Селективность — это производная кардинальности, показывающая долю отбираемых строк. Индекс с кардинальностью 1000 на таблице в 1 млн строк имеет селективность 0.1% и очень эффективен.

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