Чи є приріст продуктивності при індексації булевого поля?


103

Я тільки збираюся написати запит, що включає в себе a WHERE isok=1. Як випливає з назви, isokє булевим полем (насправді a, TINYINT(1) UNSIGNEDяке встановлюється на 0 або 1 за потреби).

Чи є приріст продуктивності при індексації цього поля? Чи буде двигун (InnoDB в даному випадку) краще чи гірше шукати індекс?


Відповіді:


80

Не зовсім. Ви повинні думати про це, як про книгу. Якби у книзі було лише 3 види слів, і ви їх індексуєте, у вас буде така ж кількість вказівних сторінок, що і у звичайних сторінках.

Якщо ви будете мати відносно мало записів, що мають одне значення, було б збільшення продуктивності. Наприклад, якщо у вас є 1000 записів, і 10 з них ПРАВИЛЬНІ, то це буде корисно, якщо ви здійснюєте пошукisok = 1

Як згадував Майкл Дюрант, це також робить процес повільніше.

EDIT: Можливе дублювання: Індексація булевих полів

Тут пояснюється, що навіть якщо у вас індекс, якщо у вас занадто багато записів, він все одно не використовує індекс. MySQL не використовує індекс при перевірці = 1, але використовує його з = 0


4
Виглядає так "так: 2 - ні: 1". Тут хтось помиляється, але хто?
Niet the Dark Absol

4
Це не зовсім правильно, без індексу mySql потрібно сканувати всю таблицю, щоб знайти відповідні рядки.
ilanco

4
інакше він би сканував весь індекс. (що в більшості випадків так само довго)
Майкл Копер

1
Це може змінити значення. Просто скоротіть час виконання наполовину запиту, додавши лише індекс, і записи є досить рідкісними та дешевими, що нас не дуже цікавить штраф. Як і у всьому, не вважайте, міряйте (також тому, що бази даних насправді не ведуть себе так, як ви їх логічно очікували)
Eelco

6
Це передбачає рівномірний розподіл між ІСТИЧНИМ та ЛІЖНИМ. Як згадує @oucil нижче, якщо ви шукаєте булеве значення, яке є досить рідкісним, це може зайняти деякий час. Не кажучи, що ви завжди повинні індексувати, але я вважаю, що характер ваших даних і ваших запитів також має значення в більшості двигунів бази даних.
mahemoff

118

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

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


Так, хоча вам слід остаточно спробувати зрозуміти "чому" речей, завжди вимірюйте поряд і випробовуйте різні речі на вашому фактичному наборі даних, щоб побачити, чи відповідає ваша теорія дійсній поведінці двигуна db (ви були б здивовані ... )
Еелько

8
@Eelco Ви маєте рацію, але в цьому випадку результат насправді добре відповідає основній теорії. Основна думка про те, що це має бути незначним, має сенс лише у тому випадку, якщо ви приблизно на 50% наштовхнетесь на елементи, що відповідають вашому пошуку. Потім, щоб знайти 100 збігів, у БД потрібно повторити 200 елементів. Але якщо елементи відповідають лише 1% часу, знадобиться повторити 10000 предметів.
mahemoff

7
Мені подобається, коли люди насправді пробують речі на місцях і дають відгуки про ефективність, а не просто філософствують.
Віктор

WHERE my_col > 0 замість my_col = 1також, здається, допомагає швидкість
Аарон

28

Це залежить від фактичних запитів та вибірковості комбінації індекс / запит.

Випадок 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

Тоді, це залежить від того, які інші індекси у вас є. Індекс на another_column, ймовірно, буде більш вибірковим, ніж індекс, у isokякого є лише два можливі значення. Індекс на (another_column, isok)або (isok, another_column)було б навіть краще.


Я думаю, це правильніша відповідь порівняно з першою. також розподіл даних.
tyan

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.