Індекси MySQL - які найкращі практики?


208

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

Які найкращі практики для індексів MySQL?

Приклади ситуацій / дилем:

  • Якщо в таблиці є шість стовпців, і всі вони можуть шукатись, чи слід індексувати їх усі або жоден з них?

  • Які негативні наслідки від індексації на ефективність?

  • Якщо у мене стовпчик VARCHAR 2500, який можна шукати з частин мого сайту, чи варто його індексувати?


5
Ви, ймовірно, повинні змінити питання. Вибір індексів є важливою частиною для оптимізації будь-якої моделі бази даних. І на мій погляд, не пов’язаний з php.
VGE


Відповіді:


242

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

Загалом, індекс накладає впорядкування по рядках таблиці.

Для простоти, уявіть, що таблиця - це просто великий файл CSV. Щоразу, коли рядок вставляється, він вставляється в кінці . Тож "природне" впорядкування таблиці - це якраз порядок, у який вставляли рядки.

Уявіть, що у вас файл CSV завантажений у дуже рудиментарну програму електронних таблиць. Все, що ця електронна таблиця робить - це відображення даних та нумерація рядків у послідовному порядку.

Тепер уявіть, що у третьому стовпчику потрібно знайти всі рядки, які мають деяке значення "М". З огляду на те, що у вас є, у вас є лише один варіант. Ви скануєте таблицю, перевіряючи значення третього стовпця для кожного рядка. Якщо у вас багато рядків, цей метод («сканування таблиці») може зайняти багато часу!

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

Тепер у вас є гарна стратегія пошуку всіх рядків, де значення третього стовпця "M". Наприклад, ви можете виконати двійковий пошук ! Оскільки сканування таблиці вимагає, щоб ви шукали N рядків (де N - кількість рядків), двійковий пошук вимагає лише перегляду записів індексу log-n, в найгіршому випадку. Ого, це точно набагато простіше!

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

Отже, загалом, індексація створює компроміс між ефективністю читання та ефективністю запису. Без індексів вставки можуть бути дуже швидкими - двигун бази даних просто додає рядок до таблиці. Коли ви додаєте індекси, двигун повинен оновлювати кожен індекс під час виконання вставки.

З іншого боку, читання стає набагато швидшим.

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

Ваш третій сценарій трохи складніший. Якщо ви використовуєте LIKE, двигуни індексації, як правило, допоможуть зі швидкістю читання до першого "%". Іншими словами, якщо ви вибираєте, де стовпець НЕОБХІДНОСЬОГО foo% bar% ', база даних використовує індекс, щоб знайти всі рядки, де стовпець починається з "foo", а потім потрібно сканувати цей проміжний набір рядків, щоб знайти підмножину що містить "бар". ВИБІР ... ГДО, де стовпець LIKE '% bar%' не може використовувати індекс. Я сподіваюся, ви можете зрозуміти, чому.

Нарешті, вам потрібно почати думати про індекси на декількох стовпцях. Концепція така ж, і поводиться аналогічно речей LIKE - по суті, якщо у вас є індекс на (a, b, c), двигун продовжить використовувати індекс зліва направо якнайкраще. Таким чином, для пошуку за стовпцем a може використовуватися індекс (a, b, c), як і на (a, b). Однак двигуну потрібно було б сканувати повну таблицю, якщо ви шукали, де б = 5 І с = 1)

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


10
Що з FULLTEXTіндексами? Чи можуть вони допомогти при таких умовах LIKE '%bar%'?
Септаграм

2
@Septagram - FULLTEXTможе допомогти з цим запитом, якщо bar це "слово". FULLTEXTобробляє слова, а не довільні підрядки (як LIKEце робиться).
Рік Джеймс

@timdev чітко в якій частині відповів на перше запитання? Я можу виявити друге та третє запитання, відповіді в першій та другій частині (до та після Надії, що охоплює ваші перші два питання ) вашої цінної відповіді
Мануель Йордан

1
@ManuelJordan - Не існує простої відповіді на перше запитання. Це залежить від того, як ви хочете збалансувати компроміси в контексті очікуваного (а ще краще, спостережуваного) використання.
timdev

57

Ознайомтеся з такими презентаціями, як More Mastering Art of Indexing .

Оновлення 12/2012: Я опублікував нову презентацію шахти: Як правильно проектувати індекси . Я представив це в жовтні 2012 року в ZendCon в Санта-Кларі, а в грудні 2012 року в Лондоні Percona Live.

Створення найкращих індексів - це процес, який повинен відповідати запитам, які ви виконуєте у вашій програмі.

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

Так, є накладні витрати, тому не слід створювати індекси без потреби. Але вам слід створити індекси, які приносять користь запитам, які потрібно швидко запустити. Накладні витрати індексу зазвичай значно перевищують його користь.

Для стовпця, що становить VARCHAR (2500), ви, ймовірно, хочете використовувати індекс FULLTEXT або індекс префікса:

CREATE INDEX i ON SomeTable(longVarchar(100));

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


3
Дуже дякую. Slieshare.net/matsunobu/… справді був дуже корисним.
Бішаль Паудель



1
Дивовижна презентація (та з 2012 року), справді зрозуміла всю точку покажчиків.
DarkteK

46

Я не повторюю кілька корисних порад в інших відповідях, але додам:

Індекси сполук

Можна створити складні індекси - індекс, що включає кілька стовпців. MySQL може використовувати їх з вліво , щоб право . Тож якщо у вас є:

Table A
Id
Name
Category
Age
Description

якщо у вас є складний індекс, який включає ім'я / категорію / вік у цьому порядку, ці пункти WHERE будуть використовувати індекс:

WHERE Name='Eric' and Category='A'

WHERE Name='Eric' and Category='A' and Age > 18

але

WHERE Category='A' and Age > 18

не використовував би цей індекс, оскільки все треба використовувати зліва направо.

Поясніть

Використовуйте Explain / Explain Extended, щоб зрозуміти, які індекси доступні для MySQL та який саме він вибирає. MySQL використовуватиме лише один ключ на запит .

EXPLAIN EXTENDED SELECT * from Table WHERE Something='ABC'

Журнал повільних запитів

Увімкніть журнал повільних запитів, щоб побачити, які запити працюють повільно.

Широкі колони

Якщо у вас є широкий стовпець, де МОСТ розрізнення відбувається в перших кількох символах, ви можете використовувати лише перші N символів у вашому індексі. Приклад: У нас стовпчик ReferenceNumber визначений як varchar (255), але в 97% випадків номер посилання становить 10 символів або менше. Я змінив індекс, щоб лише подивитися на перші 10 символів і трохи покращив продуктивність.


У мене питання про останню частину. Я десь читав, що якщо ви створюєте стовпець з VARCHAR, ви завжди повинні встановлювати його на 255. Тепер ви сказали, що індекс, встановлений для цього типу стовпців, може обмежуватися лише для перших 10 символів. Як саме ви можете це зробити?
AlexioVay

20

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

Ви шукаєте на полі польових засадах чи шукаєте декілька полів? На яких полях найбільше шукають? Які типи полів? (Індекс працює краще для INT, наприклад, для VARCHAR). Ви намагалися використовувати EXPLAIN для запущених запитів?

Які негативні наслідки від індексації на результативність

ОНОВЛЕННЯ та ВСТАВКИ будуть повільнішими. Також є додаткові потреби у сховищі, але це зазвичай неважливо.

Якщо у мене стовпчик VARCHAR 2500, який можна шукати з частин мого сайту, я повинен індексувати його

Ні, якщо це не УНІКАЛЬНО (що означає, що це вже індексовано) або ви шукаєте лише точні збіги в цьому полі (не використовуючи LIKE або повнотекстовий пошук mySQL).

Як правило, я ставлю індекс на будь-які поля, які я буду шукати або вибирати за допомогою пункту WHERE

Я зазвичай індексую поля, які найбільш запитуються, а потім INT / BOOLEANs / ENUMs, а не поля, які є VARCHARS. Не забувайте, часто вам потрібно створити індекс на комбінованих полях, а не індекс на окремому полі. Використовуйте EXPLAIN та перевіряйте повільний журнал.


11

Ефективно завантажуйте дані : Індекси прискорюють пошук, але сповільнюють вставки та видалення, а також оновлення значень в індексованих стовпцях. Тобто індекси сповільнюють більшість операцій, що передбачають написання. Це відбувається тому, що для написання рядка потрібно писати не лише рядки даних, але також потрібно змінювати будь-які індекси. Чим більше індексів має таблиця, тим більше змін потрібно внести і тим більше середня деградація продуктивності. Більшість таблиць отримують багато читань і мало записів, але для таблиці з високим відсотком записів вартість оновлення індексу може бути значною.

Уникайте індексів . Якщо вам не потрібен конкретний індекс, який допоможе запитам виконувати ефективніші показники, не створюйте його.

Дисковий простір : індекс займає місце на диску, а кілька індексів займають відповідно більше місця. Це може призвести до того, що ви швидше досягнете обмеження розміру таблиці, ніж якщо немає індексів. По можливості уникайте індексів.

Винос: Не перевищуйте індекс


5

Загалом, індекси допомагають прискорити пошук бази даних, що має недолік у використанні додаткового місця на диску та уповільненні INSERT/ UPDATE/ DELETEзапитів. Використовуйте EXPLAINта читайте результати, щоб дізнатися, коли MySQL використовує ваші індекси.

Якщо в таблиці є шість стовпців, і всі вони можуть шукатись, я повинен індексувати їх усіх або жодну з них?

Індексація всіх шести стовпців не завжди є найкращою практикою.

(a) Чи збираєтесь ви використовувати будь-який із цих стовпців під час пошуку конкретної інформації?

(b) Яка вибірковість цих стовпців (скільки чітких значень зберігається в порівнянні із загальною кількістю записів у таблиці)?

MySQL використовує оптимізатор на основі витрат, який намагається знайти «найдешевший» шлях при виконанні запиту. І поля з низькою вибірковістю не є хорошими кандидатами.

Які негативні наслідки від індексації на результативність?

Вже відповів: додатковий простір на диску, нижча продуктивність під час вставки - оновлення - видалення.

Якщо у мене є стовпчик VARCHAR 2500, який можна шукати з частин мого сайту, чи варто його індексувати?

Спробуйте індекс FULLTEXT .


4

1/2) Індекси прискорюють деякі вибрані операції, але вони сповільнюють інші операції, такі як вставлення, оновлення та видалення. Це може бути прекрасний баланс.

3) використовувати повний текстовий індекс або, можливо, сфінкс


Для запобігання slow down other operations like insert, update and deletesможна використовувати START TRANSACTION; YOUR CODE HERE; COMMIT Що може допомогти уникнути slowing downінших операцій, оскільки воно перевірятиме лише один раз обмеження один раз. CAVEAT: Якщо ви використовуєте REPLACE INTOі ваш SQL_MODE<> STRICT_ALL_TABLESАБО будете ігнорувати замінити в і вставці дублів. TRADITIONALBulk Load
JayRizzo

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