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

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)было бы еще лучше.

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

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

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

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

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

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

Джинли
источник
5

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

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

Майкл Даррант
источник
3

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

Максим Польща
источник
2

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

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

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

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

Иланко
источник
2
Индекс дает много данных на жестком диске и замедляет запись, поэтому вы не получаете от этого только выгоду.
Майкл Копер,
1
Верно, но в этом случае TINYINT(1) UNSIGNEDстолбец, размер данных будет небольшим.
ilanco
И дополнительные накладные расходы на запись, вероятно, довольно низкие
Eelco
Разве размер индекса не будет расти вместе с количеством строк, на которые он указывает, а не только с размером индексированного поля?
poolie