Два індексних індексів проти одного двоколонкового індексу в MySQL?


113

Я стикаюся з наступним і не впевнений, що найкраща практика.

Розглянемо наступну таблицю (яка вийде великою):

ід ПК | giver_id FK | получатель_id FK | дата

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

SELECT...WHERE giver_id = x AND recipient_id = t.

Кожна така комбінація буде унікальною у таблиці.

Чи є якась користь від додавання двоколонкового індексу над цими стовпцями, чи два теоретичні індекси були б теоретично достатніми / однаковими?


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

"MySQL може використовувати індекси з декількома стовпцями для запитів, які перевіряють усі стовпці в індексі, або запитів, які перевіряють лише перший стовпець, перші два стовпці, перші три стовпці тощо. Якщо ви вказуєте стовпці праворуч порядку у визначенні індексу, один складений індекс може прискорити декілька видів запитів в одній таблиці ". - декілька стовпців індексів
AlikElzin-kilaka

Екстраполювати на @ user1585784; Якщо поєднання двох стовпців унікальне, я думаю, що слід використовувати для них унікальний ключ. Насправді, якщо хочеться нав'язати унікальність на рівні бази даних, унікальний ключ - це найпростіший шлях ...
Ерк

Відповіді:


132

Якщо у вас є два індекси одного стовпця, у вашому прикладі буде використаний лише один.

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

Іноді може бути корисним індекс на (A, B) та інший індекс на (B). Це робить запити з використанням одного або обох стовпців швидкими, але, звичайно, використовується також більше місця на диску.

Вибираючи індекси, ви також повинні враховувати вплив на вставлення, видалення та оновлення. Більше індексів = повільніше оновлення.


1
"MySQL може використовувати індекси з декількома стовпцями для запитів, які перевіряють усі стовпці в індексі, або запитів, які перевіряють лише перший стовпець, перші два стовпці, перші три стовпці тощо. Якщо ви вказуєте стовпці праворуч порядку у визначенні індексу, один складений індекс може прискорити декілька видів запитів в одній таблиці ". - декілька стовпців індексів
AlikElzin-kilaka

33

Індекс покриття, як:

ALTER TABLE your_table ADD INDEX (giver_id, recipient_id);

... означало б, що індекс може бути використаний, якщо запит, на який посилається giver_id, або комбінація giver_idта recipient_id. Зверніть увагу, що критерії індексу базуються лише вліво - запит, що посилається лише на те recipient_id, не міг би використовувати індекс покриття у наданому мені виписці

Крім того, MySQL може використовувати лише один індекс на SELECT, тому покривний індекс стане найкращим засобом оптимізації ваших запитів.


10
MySQL can only use one index per SELECTце вже не так, було б добре, якби ви редагували свою відповідь, щоб оновитись.
Давор

Ви б не могли пояснити, чому індекс покриття не вдасться використати recipient_id?
Іво Перейра

2
@IvoPereira Індекси кількох стовпців у MySQL дозволяють використовувати всі поля в індексі зліва направо. Наприклад, якщо у вас є, INDEX (col1, col2, col3, col4)тоді індекс буде застосовано для пошуку з WHEREпунктом типу « col1 = 'A'або», col1 = 'A' AND col2 = 'B'або col1 = 'A' AND col2 ='B' AND col3 = 'C' AND col4 = 'D', але цей конкретний індекс не буде використовуватися для нічого подібного WHERE col2 = 'B'або WHERE col3 = 'C' AND col4 = 'D'тому, що поля пошуку не залишаються найбільше у визначенні індексу. Вам потрібно буде додати додаткові індекси для покриття цих полів.
Slicktrick

"один індекс на SELECT" , це все-таки вірно для mariadb 10.1?
oldboy

1
@Anthony: Ні. Див. Коментар Давора вище.
капад

4

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

Інша річ, що слід враховувати, якщо ви можете усунути поле ПК у цій таблиці та визначити індекс первинного ключа на полях giver_idта recipient_id. Ви сказали, що комбінація унікальна, так що, можливо, спрацює (зважаючи на безліч інших умов, на які ви можете відповісти лише ви). Однак, як правило, я вважаю, що додаткова складність, яка додає, не вартує клопоту.


Дякую Марку, одна з клавіш справді дуже вибірна, тому має бути добре. Я вирішив утримати два (автоматичні) індекси на місці та побачити, як він працює з часом. Я також думав про комбінований первинний ключ, який надає: отримувач, але оскільки кожне поле також потрібно шукати окремо, це просто додасть php накладні витрати. Також новий ключ буде (довшим) рядком замість (коротшого) цілого числа.
Том

2

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


ви можете, будь ласка, посилатися на якусь документацію навколо цього Дякую.
капад
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.