Добавить в корзинуПозвонить
Найти в Дзене
Oracle Developer

Composite Index: какую колонку поставить первой

Composite Index: какую колонку поставить первой? Коллеги, всем привет! Этот вопрос волнует и Junior-, и Middle-, и даже Senior-разработчиков: как правильно выбрать порядок колонок в составном индексе? Казалось бы, простой вопрос: есть таблица, есть запрос с условиями по нескольким колонкам — создаём составной индекс. Но в каком порядке расположить колонки? Ответ не так очевиден, как кажется, и зависит от нескольких факторов. Что такое селективность? Селективность колонки — это отношение уникальных значений к общему количеству строк. Чем выше селективность, тем меньше строк возвращается при фильтрации по этой колонке. Примеры: 🔹 Высокая селективность: ID сотрудника, email, номер паспорта (почти все значения уникальны) 🔹 Низкая селективность: пол (M/F), статус (Y/N), тип документа (5-10 значений) Традиционная рекомендация — ставить первой колонку с наибольшей селективностью. Логика проста: Oracle быстрее отфильтрует большую часть строк. Пример: -- Таблица сотрудников CREATE INDEX

Composite Index: какую колонку поставить первой?

Коллеги, всем привет!

Этот вопрос волнует и Junior-, и Middle-, и даже Senior-разработчиков: как правильно выбрать порядок колонок в составном индексе?

Казалось бы, простой вопрос: есть таблица, есть запрос с условиями по нескольким колонкам — создаём составной индекс. Но в каком порядке расположить колонки? Ответ не так очевиден, как кажется, и зависит от нескольких факторов.

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

Селективность колонки — это отношение уникальных значений к общему количеству строк. Чем выше селективность, тем меньше строк возвращается при фильтрации по этой колонке.

Примеры:

🔹 Высокая селективность: ID сотрудника, email, номер паспорта (почти все значения уникальны)

🔹 Низкая селективность: пол (M/F), статус (Y/N), тип документа (5-10 значений)

Традиционная рекомендация — ставить первой колонку с наибольшей селективностью. Логика проста: Oracle быстрее отфильтрует большую часть строк.

Пример:

-- Таблица сотрудников

CREATE INDEX idx_emp_composite

ON employees(employee_id, department_id, status);

Здесь employee_id имеет высокую селективность (уникальные значения), department_id — среднюю (10-20 отделов), status — низкую (активен/неактивен).

Если ваш запрос использует все три колонки или начинается с employee_id, такой индекс будет работать отлично:

SELECT * FROM employees

WHERE employee_id = 12345

AND department_id = 10

AND status = 'A';

Но есть нюанс!

Что если ваши запросы чаще фильтруют по department_id и status, а employee_id используется редко? Тогда индекс с employee_id первым становится бесполезным для большинства запросов.

Анализируйте ваши запросы

Первой должна быть колонка, которая чаще всего используется в WHERE-условиях. Даже если её селективность ниже.

Пример:

-- Частый запрос

SELECT * FROM employees

WHERE department_id = 10

AND status = 'A';

-- Лучший индекс для этого случая

CREATE INDEX idx_dept_status

ON employees(department_id, status);

Index Skip Scan и низкая селективность

Oracle умеет использовать составные индексы, даже если первая колонка не участвует в запросе — это называется Index Skip Scan. Но это работает эффективно только если первая колонка имеет низкую кардинальность (мало уникальных значений).

Пример:

CREATE INDEX idx_status_empid

ON employees(status, employee_id);

-- Запрос без первой колонки

SELECT * FROM employees

WHERE employee_id = 12345;

Oracle может ""перепрыгнуть"" через status (всего 2 значения: Y/N) и использовать индекс. Но если первая колонка имеет тысячи уникальных значений, Skip Scan будет неэффективен.

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

Допустим, у вас таблица заказов. Типичные запросы:

-- Запрос 1: поиск по клиенту и статусу

SELECT * FROM orders

WHERE customer_id = 1001 AND status = 'PENDING';

-- Запрос 2: поиск по дате и статусу

SELECT * FROM orders

WHERE order_date BETWEEN DATE '2024-01-01' AND DATE '2024-12-31'

AND status = 'SHIPPED';

Решение:

-- Для запроса 1

CREATE INDEX idx_cust_status

ON orders(customer_id, status);

-- Для запроса 2

CREATE INDEX idx_date_status

ON orders(order_date, status);

Обратите внимание: status имеет низкую селективность, но он присутствует в обоих запросах, поэтому идёт вторым.

Итого

Выбор порядка колонок в составном индексе — это баланс между:

🔹 Частотой использования колонки в запросах (главный фактор)

🔹 Селективностью колонки (высокая селективность первой — хорошо)

🔹 Возможностью Index Skip Scan (низкая кардинальность первой колонки помогает)

Не существует универсального правила. Анализируйте ваши реальные запросы, смотрите execution plans, тестируйте разные варианты. Конечно же, на курсе по Оптимизации мы это подробно разбираем.

А как вы решаете, какую колонку поставить первой в составном индексе? Напишите в чатике 💬

#oracle #compositeindex #оптимизация

Канал Oracle Developer | Чатик 💬

Мини-курс Оптимизация: Быстрый старт 🚀

Анкета предзаписи на 7 поток "Оптимизация Oracle SQL" 🔥

📱 Facebook 📱 YouTube 📱 ВКонтакте 📱 LinkedIn 📱 Threads RUTUBE