Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Index Merge: Intersection, Union, Sort-Union
index_merge_intersection

Index Merge: Intersection, Union, Sort-Union

Использование нескольких индексов в одном запросе, алгоритмы объединения

Index Merge: Intersection, Union, Sort-Union

Index Merge — это стратегия оптимизатора, при которой MySQL использует несколько индексов одновременно для одного запроса и объединяет их результаты. Это альтернатива составному индексу, когда его нет.

#Когда возникает Index Merge

Представьте таблицу с двумя отдельными индексами:

CREATE TABLE tasks ( id BIGINT PRIMARY KEY, status VARCHAR(20), priority VARCHAR(20), assignee_id INT, INDEX idx_status (status), INDEX idx_priority (priority) );

Запрос с двумя условиями по разным столбцам:

EXPLAIN SELECT * FROM tasks WHERE status = 'open' AND priority = 'high';

Без составного индекса (status, priority) оптимизатор может использовать Index Merge:

type: index_merge
key: idx_status,idx_priority
Extra: Using intersect(idx_status,idx_priority)

#Intersection (пересечение)

Используется для запросов с AND:

-- Оба условия должны выполняться SELECT * FROM tasks WHERE status = 'open' AND priority = 'high';

Алгоритм:

  1. Сканирует idx_status, получает набор rowid для 'open'
  2. Сканирует idx_priority, получает набор rowid для 'high'
  3. Находит пересечение — rowid, присутствующие в обоих наборах
  4. Для найденных rowid — lookup по кластерному индексу

Это эффективнее full table scan, если оба условия селективны. Но составной индекс (status, priority) почти всегда быстрее — один поиск вместо двух + пересечение.

#Union (объединение)

Используется для запросов с OR:

-- Любое из условий SELECT * FROM tasks WHERE status = 'open' OR priority = 'high';

Алгоритм:

  1. Сканирует idx_status, получает rowid для 'open'
  2. Сканирует idx_priority, получает rowid для 'high'
  3. Объединяет оба набора rowid (union)
  4. Для уникальных rowid — lookup по кластерному индексу

Union полезен, когда каждое условие по отдельности селективно, но ни одно не покрывает весь запрос.

#Sort-Union

Используется для OR с диапазонными условиями:

-- Диапазонные условия с OR SELECT * FROM tasks WHERE created_at > '2024-01-01' OR updated_at > '2024-06-01';

Sort-Union отличается от обычного Union тем, что сортирует rowid перед объединением. Это необходимо, потому что диапазонные условия не позволяют напрямую объединить rowid — их нужно сначала упорядочить. Сортировка добавляет owerhead, но обеспечивает корректность.

#Index Merge vs составной индекс

Index Merge — это 'план Б'. Вот почему составной индекс почти всегда лучше:

-- Index Merge: два отдельных индекса -- 2 сканирования индексов + пересечение rowid + lookup CREATE INDEX idx_status ON tasks(status); CREATE INDEX idx_priority ON tasks(priority); -- Составной индекс: один поиск -- 1 сканирование + lookup CREATE INDEX idx_comp ON tasks(status, priority);

Сравнение:

МетрикаIndex MergeСоставной индекс
Чтений индексов21
Операций пересеченияДаНет
Rowid для lookupБольше (менее точный)Меньше (точный)
Covering indexНет (обычно)Возможен

#Когда Index Merge полезен

Index Merge имеет смысл, когда:

  • Невозможно создать составной индекс (слишком много комбинаций запросов)
  • Каждый отдельный индекс очень селективен
  • Запрос редкий и owerhead приемлем
-- Index Merge может быть выбран вместо составного индекса, -- если есть МНОГО разных комбинаций запросов -- и создание всех составных индексов невозможно

#Отключение Index Merge

Иногда Index Merge дороже альтернатив. Его можно отключить:

-- Для конкретного запроса — игнорировать индексы SELECT * FROM tasks IGNORE INDEX (idx_status, idx_priority) WHERE status = 'open' AND priority = 'high'; -- Глобально (не рекомендуется) SET SESSION optimizer_switch = 'index_merge=off';

Зачем отключать: если один из индексов значительно лучше другого, лучше использовать только его + фильтрация. Index Merge может добавить owerhead пересечения без существенного сокращения строк.

#Диагностика

В EXPLAIN Index Merge легко обнаружить:

EXPLAIN SELECT * FROM tasks WHERE status = 'open' AND priority = 'high';
type: index_merge
key: idx_status,idx_priority
key_len: 62,62
ref: NULL
rows: 150
Extra: Using intersect(idx_status,idx_priority)

Если вы видите index_merge — подумайте, не будет ли составной индекс эффективнее. Если составной индекс невозможен — убедитесь, что rows для Index Merge разумно мал.

Далее: Оптимизация JOIN запросов