Есть ли прирост производительности при индексировании логического поля?


104

Я как раз собираюсь написать запрос, включающий расширение WHERE isok=1. Как следует из названия, isokэто логическое поле (фактически TINYINT(1) UNSIGNED, для которого установлено значение 0 или 1 по мере необходимости).

Есть ли прирост производительности при индексировании этого поля? Будет ли движок (в данном случае InnoDB) работать лучше или хуже при поиске по индексу?


Ответы:


82

На самом деле, нет. Вы должны думать об этом как о книге. Если бы в книге было всего 3 вида слов и вы все их индексировали, у вас было бы такое же количество индексных страниц, как и у обычных страниц.

Если имеется относительно мало записей с одним значением, производительность повысится. Например, если у вас есть 1000 записей и 10 из них ИСТИНА, было бы полезно, если бы вы выполняли поиск с помощьюisok = 1

Как сказал Майкл Даррант, это также замедляет запись.

РЕДАКТИРОВАТЬ: возможное дублирование: индексирование логических полей

Здесь объясняется, что даже если у вас есть индекс, если у вас слишком много записей, индекс все равно не используется. MySQL не использует индекс при проверке = 1, но использует его с = 0


4
Похоже, это «да: 2 - нет: 1». Здесь кто-то не прав, но кто?
Niet the Dark Absol

4
Это не совсем правильно, без индекса mySql необходимо сканировать всю таблицу, чтобы найти соответствующие строки.
ilanco

4
в противном случае он будет сканировать весь индекс. (который в большинстве случаев такой же длинный)
Майкл Копер,

1
Это может иметь значение. Просто сократите время выполнения вдвое, просто добавив индекс, и записи будут редкими и достаточно дешевыми, чтобы нас не волновали штрафы. Как и во всем, не предполагайте, измеряйте (также потому, что базы данных на самом деле не всегда ведут себя так, как вы логически ожидаете от них)
Eelco

6
Это предполагает равное распределение значений ИСТИНА и ЛОЖЬ. Как упоминается ниже @oucil, если вы ищете логическое значение, которое встречается довольно редко, это может занять некоторое время. Не говорю, что вы всегда должны индексировать, но я предполагаю, что характер ваших данных и ваших запросов также имеет значение для большинства движков баз данных.
mahemoff

118

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

У нас есть таблица с примерно 4 миллионами строк, только около 1000 или около того за раз будут отмечены логическим переключателем, и это то, что мы ищем. Добавление индекса в наше логическое поле ускорило запросы на порядки, оно увеличилось с 9+ секунд до долей секунды.


Да, хотя вы должны окончательно попытаться понять «почему» вещей, всегда измеряйте параллельно и пробуйте разные вещи в своем фактическом наборе данных, чтобы увидеть, совпадает ли ваша теория с реальным поведением движка db (вы будете удивлены ... )
Eelco

8
@Eelco Вы правы, но в этом случае результат действительно хорошо согласуется с основной теорией. Основная идея о том, что им можно пренебречь, имеет смысл только в том случае, если вы с вероятностью 50% встретите элементы, соответствующие вашему запросу. Затем, чтобы найти 100 совпадений, БД необходимо перебрать 200 элементов. Но если элементы совпадают только в 1% случаев, потребуется перебрать 10 000 элементов.
mahemoff

7
Мне нравится, когда люди действительно пробуют что-то на поле и дают обратную связь, а не просто философствуют.
Виктор Жорас

WHERE my_col > 0 вместо того my_col = 1, чтобы, кажется, также помогает скорости
Аарон

29

Это зависит от реальных запросов и избирательности комбинации индекса / запроса.

Случай A : состояние WHERE isok = 1и ничего другого:

SELECT *
FROM tableX
WHERE isok = 1
  • Если индекс достаточно селективен (скажем, у вас 1 миллион строк и только 1 КБ isok = 1), тогда механизм SQL, вероятно, будет использовать индекс и будет быстрее, чем без него.

  • Если индекс недостаточно избирательный (скажем, у вас 1 миллион строк, а их более 100 тысяч isok = 1), то механизм SQL, вероятно, не будет использовать индекс и выполнять сканирование таблицы.

Случай B : состояние WHERE isok = 1и многое другое:

SELECT *
FROM tableX
WHERE isok = 1
  AND another_column = 17

Затем это зависит от того, какие еще у вас индексы. Индекс on another_column, вероятно, будет более избирательным, чем индекс, isokкоторый имеет только два возможных значения. Индекс на (another_column, isok)или (isok, another_column)было бы еще лучше.


Думаю, это более правильный ответ по сравнению с верхним. также распределение данных.

12

Это зависит от распределения данных.

Представьте, что у меня есть книга с 1000 тщательно напечатанными страницами, и единственными словами в моей книге были «да» и «нет», повторяющиеся снова и снова и распределяемые случайным образом. Если бы меня попросили обвести все «да», поможет ли указатель в конце книги? Это зависит.

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

Но если бы в моей тысячестраничной книге было, скажем, всего десять случаев «да», а все остальное было бы просто миллионами «нет», то указатель сэкономил бы мне массу времени на поиск этих десяти случаев «да» и обход их. .

То же самое и с базами данных. Если это распределение 50:50, то индекс не поможет - движку базы данных лучше просто пропахать данные от начала до конца (полное сканирование таблицы), а индекс просто сделает базу данных больше, и медленнее писать и обновлять. Но если это что-то вроде распределения 4000: 1 (как указано в этой ветке), то поиск по индексу может значительно ускорить его, если вы ищете 1 элемент из 4000.


5

Нет, обычно нет.

Обычно вы индексируете поля для поиска, когда они имеют высокую избирательность / количество элементов. Мощность логического поля в большинстве таблиц очень мала. Это также сделало бы вашу запись немного медленнее.


3

На самом деле это зависит от выполняемых вами запросов. Но, как правило, да, как и индексация поля любого другого типа.


2

Да, индекс повысит производительность, проверьте вывод EXPLAIN с индексом и без него.

Из документов:

Индексы используются для быстрого поиска строк с определенными значениями столбцов. Без индекса MySQL должен начать с первой строки, а затем прочитать всю таблицу, чтобы найти соответствующие строки. Чем больше таблица, тем больше это стоит. Если таблица имеет индекс для рассматриваемых столбцов, MySQL может быстро определить позицию для поиска в середине файла данных, не просматривая все данные.

Я также думаю, что в этом случае можно с уверенностью сказать, что индекс не УМЕНЬШИТ производительность, поэтому вам нужно только выиграть от него.


2
Индекс дает много данных на жестком диске и замедляет запись, поэтому вы не получаете от этого только выгоду.
Майкл Копер,

1
Верно, но в этом случае TINYINT(1) UNSIGNEDстолбец, размер данных будет небольшим.
ilanco

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

Разве размер индекса не будет расти вместе с количеством строк, на которые он указывает, а не только с размером индексированного поля?
poolie
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.