Составной индекс имеет направление в MySQL?
Когда будет необходимо следующее:
create index i_t_a_b on t(a,b);
create index i_t_b_a on t(b,a);
2 ответа
Если вы хотите получить максимальную скорость извлечения и иметь оба столбца в соединении или в определенных условиях, НО иногда столбец a имеет более высокую избирательность, а иногда столбец b имеет более высокую избирательность, и вы хотите извлечь выгоду из этого факта из одного индекса.
Кроме того, я думаю, что ваше соотношение размера данных / производительности машины должно быть достаточно высоким, и в то же время вам придется (догадываясь) назвать любое улучшение необходимостью (даже если только на несколько процентов).
Тем не менее, опыт учит, что все зависит от многих факторов; с конкретными СУБД и средами приложений вы лучше запускаете свои собственные тесты.
РЕДАКТИРОВАТЬ: Дальнейшее объяснение составных индексов. из википедии:
"Порядок, в котором столбцы перечислены в определении индекса, важен. Можно получить набор идентификаторов строк, используя только первый индексированный столбец. Однако невозможно (или в большинстве баз данных) получить набор идентификаторы строк, использующие только второй или больший индексированный столбец.
Например, представьте телефонную книгу, которая организована сначала по городу, затем по фамилии, а затем по имени. Если вам указан город, вы можете легко извлечь список всех телефонных номеров этого города. Тем не менее, в этой телефонной книге было бы очень утомительно найти все номера телефонов для данной фамилии. Вы должны искать в разделе каждого города записи с этой фамилией."
Объяснения Википедии, возможно, чрезмерно упрощены, но они дают вам основную идею (поскольку аналогии идут, имейте в виду, что телефонные книги обычно имеют кластеризованные индексы, и это не будет вашим общим индексом базы данных).
В зависимости от размера индекса в зависимости от размера структуры данных в зависимости от доступной памяти в зависимости от селективности в первом столбце индекса использование индекса, упорядоченного по порядку, может быть значительно дешевле, чем сканирование таблицы.
Ах, просто подумал о лучшей аналогии с примером, который вы ищете. Представьте себе хороший учебник, в котором будет оглавление с главами и подразделами, а также количество страниц, на которых они находятся (это некластерный индекс, содержащий указатели). на записи данных - страницы). Теперь представьте, что учебник по стандарту SQL-92, тогда большинство терминов в оглавлении будут терминами SQL (придерживайтесь этого предположения). У вас также будет другой указатель в конце книги, в котором будут перечислены все интересные термины в алфавитном порядке (предположим, с основными названиями глав) и номера страниц.
Для такого вопроса, как "Скажите мне все главы, в которых появляется DISTINCT", вы должны использовать второй индекс. (потому что селективность более позднего поля высока)
Для таких вопросов, как "Скажите мне количество терминов, которые появляются в первой главе", вы бы использовали TOC
Так что для таких вопросов, как "Описан ли SELECT в главе DML?" Вы можете использовать любой из индексов. (потому что селективность обоих полей высока) Однако, если TOC самого DML имеет длину 3 страницы, а запись SELECT в индексе содержит только пятнадцать строк, вы, вероятно, перейдете ко второй, и это пример того, когда вы получаете выгоду от обоих индексов.
Теперь, если вы думаете, что это слишком надумано, примите во внимание базу данных отсканированной библиотеки конгресса.:)
Как я уже говорил, все планирование в порядке, но в конце все же запустите свои собственные тесты.
Я не думаю, что есть какой-то реальный случай, когда вам это нужно.
Это может иметь смысл, когда в вашей таблице гораздо больше столбцов, a
а также b
не являются уникальными, и вам нужна высокая производительность для обоих следующих запросов:
Select Max(b) From t Where a=1 --# Would use i_t_a_b
а также
Select Max(a) From t Where b=1 --# Would use i_t_b_a
Допустим, ваш стол выглядит так:
a b c d e
- - - - -
0 8 x x x
0 9 x x x
1 8 x x x
1 9 x x x
i_t_a_b
выглядит примерно так:
0
8
9
1
8
9
i_t_b_a
выглядит примерно так:
8
0
1
9
0
1
Select Max(b) From t Where a=1
придется копаться в 8
а также 9
из i_t_b_a
найти все строки с a=1
, Это все еще намного быстрее, чем сканирование полной таблицы (нужно прочитать все x
тоже), но это не так быстро, как при использовании i_t_a_b
,