Найкращі практики, які слід дотримуватися з індексів баз даних [закрито]


17

Які існують ДО та НЕ для покращення продуктивності бази даних за допомогою індексу?

DO - це випадок, коли слід створити індекс, або інший підказки, пов'язані з індексами, що підвищить ефективність.

DONT буде випадком, коли індекс не повинен створюватися, або інша дія, пов’язана з індексом, яка може зашкодити продуктивності.


3
профіль, профіль, профіль
GrandmasterB

Відповіді:


15

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

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

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

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


17

Це дуже залежить від того, як ви використовуєте свої таблиці. Єдиної і простої відповіді немає.

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

Вони існують для SQL Server та Oracle . Я не знаю, чи є їх у інших СУБД, просто сумніваюся, що вони не надають таких основних інструментів.

Мало випадкових рекомендацій:

  • Індекси забезпечують високу ефективність при застосуванні до стовпців, часто включених у пункт WHERE
  • Використовуйте індекс кластера для найбільш часто використовуваних стовпців у ваших запитах.
  • Не забувайте, що ви можете створювати кілька індексів за допомогою комбінації стовпців (як вони використовуються у ваших запитах)
  • Наявність багатьох індексів зменшить ефективність команд INSERT.

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


2
+1 для покажчиків на комбінаціях стовпців. Індекси стовпців aі bце НЕ те ж саме , як індекс на (a, b). Останнє майже таке ж добре, як і індекс aдля прискорення запитів із умовою увімкнено a, значно краща для запитів із умовами aта b, і не корисна для запитів bокремо. (Більшість баз даних не використовуватимуть це. Oracle буде, але не виходить з нього пробіг, який він регулярно робить.)
btilly

2
+1, додасть "навчитися читати плани запитів, щоб ти знав, що індексувати"
Стівен А. Лоу

4

@Pierre 303 вже сказав це, але я знову скажу. DO використовувати індекси на комбінаціях стовпців. Комбінований індекс у (a, b)лише дещо повільніший для запитів, aніж індекс aпоодинці, і значно краще, якщо ваш запит поєднує обидва стовпці. Деякі бази даних можуть приєднуватися до індексівa і bдо того, як потрапити в таблицю, але це не так добре, як комбінований індекс. Під час створення комбінованого індексу слід розмістити стовпець, який, швидше за все, спочатку буде шукати в комбінованому індексі.

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

Якщо ви використовуєте базу даних з справжніми тимчасовими таблицями, які ви можете створювати та знищувати на ходу (наприклад, PostgreSQL, MySQL, але не Oracle), то DO створюйте індекси на тимчасових таблицях.

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

НЕ ДАЙТЕ майте індексів на таблицях, на яких ви збираєтеся робити велике завантаження даних. Це набагато, набагато швидше скинути індекси, завантажити дані, потім відновити індекси, ніж підтримувати їх під час завантаження таблиці.

НЕ використовуйте індекси для запитів, які мають доступ до більш ніж невеликої частки великої таблиці. (Наскільки маленька залежить від обладнання. 5% - це гідне правило.) Наприклад, якщо у вас є дані з іменами та статтю, імена є хорошим кандидатом для індексації, оскільки будь-яке ім'я становить невелику частку від загальних рядків. Не було б корисно індексувати стать, оскільки вам все одно доведеться отримувати доступ до 50% рядків. Ви дійсно хочете замість цього використовувати повне сканування таблиці. Причина полягає в тому, що індекси завершують доступ до великого файлу випадковим чином, в результаті чого вам потрібно шукати диски. Пошук диска повільний. Як приклад я нещодавно мені вдалося пришвидшити запит на годину, який виглядав так:

SELECT small_table.id, SUM(big_table.some_value)
FROM small_table
  JOIN big_table
    ON big_table.small_table_id = small_table.id
GROUP BY small_table.id

до 3 хвилин, переписавши його наступним чином:

SELECT small_table.id, big_table_summary.summed_value
FROM small_table
  JOIN (
      SELECT small_table_id, SUM(some_value) as summed_value
      FROM big_table
      GROUP BY small_table_id
    ) big_table_summary
    ON big_table_summary.small_table_id =  small_table.id

що змусило базу даних зрозуміти, що вона не повинна намагатися використовувати спокусливий індекс на big_table.small_table_id. (Хороша база даних, наприклад, Oracle, повинна вирішити це самостійно. Цей запит виконувався на MySQL.)

Оновлення: Ось пояснення щодо пошуку диска, який я зробив. Індекс дає швидкий пошук, щоб сказати, де дані перебувають у таблиці. Зазвичай це виграш, оскільки ви будете дивитись лише на ті дані, які вам потрібно переглянути. Але не завжди, особливо якщо ви зрештою подивитесь на багато даних. Диски добре передають дані, але роблять пошуки повільними. Випадковий пошук даних на диску займає 1/200-ту секунду. Повільна версія запиту завершилася, зробивши щось на зразок 600 000 таких запитів, і пройшло близько години. (Це зробило більше пошукових запитів, ніж це, але кешування застало деякі з них.) На відміну від швидкої версії знали, що вона повинна прочитати все і передавати дані на швидкості 70 кб / с. Він потрапив через 11 ГБ таблиці за 3 хвилини.


Привіт, я збентежений твоїм прикладом. Я б подумав, що використання індексу зробило б справи швидше, чи не в цьому суть індексів? Ви хочете сказати, що якщо запит матиме доступ до> 5% таблиці, то індекс у стовпці, в якому ви шукаєте, зробить все повільніше?
Клацніть Upvote

@Click Upvote: Якщо до запиту звертається більше 5% (точна частка сильно залежить від обладнання та даних) таблиці, швидше не використовувати індекс для цього запиту. Якщо індекс не зашкодить, доки ви не використовуєте його. Я оновлю докладніше, чому це так.
btilly

Корисна інформація. Більше про це, наприклад, mysqlperformanceblog.com/2007/08/28/… Але мені було цікаво, чи "ігнорувати ключ" не до цього, що вам потрібно зробити підзапит?
Інка

@Inca: Мені не було відомо про "ігнорувати ключ". Я перемикаю бази даних достатньо, щоб часто існували конкретні бази даних, про які я не знаю. Зі звуків цього, що спрацювало б, але значно менш ефективно, ніж моє можливе рішення. Різниця полягала в тому, що то приєдналася б, то група, а шахта згрупувалась, то приєдналася. Це економить роботу при з’єднанні, оскільки потрібно зменшити кількість записів.
btilly

"Хороша база даних (наприклад, Oracle, але не MySQL)": будь ласка, уникайте таких дурних рекламних речей, особливо якщо ви ігноруєте факт, що MySQL може ідеально використовувати одночасно декілька індексів (відмічено "INDEX MERGE" у планах запитів) .
Патрік Аллаерт

2

DO: Індексуйте дуже мало полів, до яких ви отримуєте найбільше доступу через запит та / або порівняння.

НЕ: Індексуйте кожне поле таблиці, думаючи, що це зробить це швидше.

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


2

В основному, індекси прискорюють пошук, але сповільнюють написання, і вони займають місце. Ось і робиться компроміс.

Будь-яке поле, яке часто використовується для приєднання, пошуку / порівняння або замовлення, є кандидатом на показник. Знати, що це дійсно доброякісно, ​​міра. Однак зовнішні ключі сильно з’єднаних таблиць з великою кількістю (> 1000) записів і кількома вставками окупляться.

Для текстових полів ви можете проіндексувати частину поля (наприклад, перші 6 символів), що пришвидшило б ваш запит, але полегшило навантаження на індекси. Повний текст пошуку (пошук уlike %substring% ) потребують різних методик, з якими я не знайомий, тому я не можу дати вам там поради.

Важлива ситуація, коли індекси не допоможуть: ви не можете використовувати індекс повних полів дати або дати, коли шукаєте (/ приєднуєтесь / замовляєте) частину дати. Індекс на date_createdне допоможе вам у такому запиті select * from t where year(date_created) = 2011. У mysql ви не можете створити індекс для частини дати. (Коли ви використовуєте " between", а не year()він може використовувати індекс у полі дати.)

Більше інформації про MYSQL в посібнику: http://dev.mysql.com/doc/refman/5.6/uk/optimization-indexes.html


1

ДО: Спробуйте звести до мінімуму загальний розмір кластерного індексу. Кластеризовані записи індексу будуть включені в інші некластеризовані індекси, і звідси з'являється потенціал для витрачання дискового простору.


1

Подумайте про таблицю як про лексикон, де статті сортуються за порядком появи (або взагалі немає корисного замовлення), а індекс таблиці як індекс книги до цього лексикону.

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

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

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

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