Правильная индексация при использовании оператора ИЛИ - PullRequest
8 голосов
/ 18 августа 2011

У меня такой запрос:

SELECT fields FROM table
WHERE field1='something' OR field2='something' 
OR field3='something' OR field4='something'

Как правильно индексировать такую ​​таблицу для этого запроса?

Такой запрос занимает целую секунду! У меня есть 1 индекс со всеми 4 этими полями, поэтому я думаю, что mysql сделает что-то вроде этого:

Пройдите по каждой строке в индексе, думая так: Field1 что-то? Как насчет field2? field3? Field4? Хорошо, нет, перейдите к следующему ряду.

Ответы [ 2 ]

16 голосов
/ 18 августа 2011

Вы неправильно понимаете, как работают индексы.

Подумайте о телефонной книге (эквивалент двухколоночного индекса по имени, фамилии, имени).Если я попрошу вас найти в телефонной книге всех людей, чья фамилия - «Смит», вы сможете извлечь выгоду из того факта, что имена упорядочены таким образом;Вы можете предположить, что Смиты организованы вместе.Но если я попрошу вас найти всех людей по имени «Джон», вы не получите никакой выгоды от индекса.У Джонса может быть любая фамилия, и поэтому они разбросаны по всей книге, и вам в конечном итоге придется искать трудный путь, от обложки до обложки.

Теперь, если я попрошу вас найти всех людей, чья фамилия«Смит» ИЛИ, чье имя «Джон», вы можете легко найти Смитов, как и раньше, но это совсем не поможет вам найти Джонов.Они по-прежнему разбросаны по всей книге, и вы должны искать их трудным путем.

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

Вернуться к исходному вопросу.

Как правильно индексировать такую ​​таблицу для этого запроса?

Создайте отдельный индекс в одну колонку для каждого столбца.Один из этих индексов будет лучшим выбором, чем другие, основываясь на оценке MySQL того, сколько операций ввода-вывода будет выполнять индекс, если он будет использован.

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

Еще один прием, который многие люди успешно используют, - это сделать отдельный запрос для каждого из ваших проиндексированных столбцов (который должен использовать соответствующийиндекс), а затем UNION результаты.

SELECT fields FROM table WHERE field1='something' 
UNION
SELECT fields FROM table WHERE field2='something' 
UNION
SELECT fields FROM table WHERE field3='something' 
UNION
SELECT fields FROM table WHERE field4='something' 

Последнее замечание: если вы ищете один и тот же 'something' в четырех полях, вам следует пересмотреть, если все четыре поля на самом деле одно и то жеи вы виновны в разработке таблицы, которая нарушает форму First Normal с повторяющимися группами .Если это так, возможно, поля от field1 до field4 принадлежат одному столбцу в дочерней таблице.Тогда становится намного легче индексировать и запрашивать:

SELECT fields from table INNER JOIN child_table ON table.pk = child_table.fk
WHERE child_table.field = 'something'
0 голосов
/ 18 августа 2011

В дополнение к предыдущему комментарию: некоторые RDMS, такие как Mysql / PostgreSql, могут использовать объединение индексов, если оптимизатор считает, что это хорошая идеяТаким образом, вы можете создать разные индексы для каждого поля или создать несколько составных индексов, таких как field1, field2 и field3, field4.Наконец, вы должны попробовать несколько разных решений и выбрать лучший план объяснения.

...