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


22

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

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

Уявіть собі таку таблицю:

id int pk/uid
name varchar(50)
customerId int (foreign key)
dateCreated datetime

Я міг би побачити один індекс в тому числі name, customerIdі dateCreatedпідлогу.

Але я розумію, що такий індекс не буде використаний у запиті, наприклад:

SELECT [id], [name], [customerId], [dateCreated]
   FROM Representatives WHERE customerId=1 
   ORDER BY dateCreated

Для такого запиту мені здається, що кращою ідеєю був би індекс, включаючи поля customerIdта dateCreatedполя, при цьому customerIdполе є "першим". Це створило б індекс, який би мав дані, організовані таким чином, щоб цей запит міг швидко знайти те, що йому потрібно - у порядку, який йому потрібен.

Ще одне, що я бачу, мабуть так само часто, як і перше, - це індивідуальні індекси на кожному полі; так, один кожен на name, customerIdі dateCreatedполя.

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


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

Але я вважаю, що те, що я запитую, є загальним «відправною точкою» для індексів, чи має сенс мати конкретні індекси для конкретних, часто витягнутих запитів та полів у пунктах WHERE або ORDER BY?

Відповіді:


27

Ви праві в тому, що ваш приклад запиту не використовує цей індекс.

Планувальник запитів розгляне можливість використання індексу, якщо:

  • всі поля, що містяться в ньому, посилаються на запит
  • на деякі поля, починаючи з початку, посилаються

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

Тож для вашого прикладу:

SELECT [id], [name], [customerId], [dateCreated]
   FROM Representatives WHERE customerId=1 
   ORDER BY dateCreated

він буде враховувати такі показники, як:

[customerId]
[customerId], [dateCreated]
[customerId], [dateCreated], [name]

але не:

[name], [customerId], [dateCreated]

Якщо він знайде і те, [customerId]і [customerId], [dateCreated], [name]його рішення віддавати перевагу одному перед іншим, залежатиме від статистики індексу, яка залежить від оцінок балансу даних у полях. Якщо вони [customerId], [dateCreated]були визначені, то слід віддавати перевагу тому, що над іншими двома, якщо ви не дасте конкретний індекс натяк на протилежне.

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

Конкретні індекси для частих запитів, які в іншому випадку будуть повільними через сканування таблиці або індексів, як правило, є хорошою ідеєю, хоча не перестарайтеся, оскільки ви могли обміняти одну проблему продуктивності на іншу. Якщо ви визначитеся [customerId], [dateCreated]як індекс, наприклад, пам’ятайте, що планувальник запитів зможе використовувати його для запитів, які використовуватимуть індекс лише [customerId]за наявності. Хоча використання просто [customerId]було б трохи ефективніше, ніж використання складного індексу, це може бути пом’якшене, якщо закінчиться наявність двох індексів, які змагаються за місце в ОЗУ замість одного (хоча якщо весь ваш звичайний робочий набір легко вписується в оперативну пам’ять, ця додаткова конкуренція пам'яті може не бути питання).


+1; чудова інформація, особливо нагадування (яке я, як правило, забуваю!) про те, що планувальник може використовувати складний індекс у той час, коли для запиту йому потрібні лише перші поля (поля) від нього.
Ендрю Барбер

6

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

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

Моя стратегія проектування індексів - індексувати:

  • Поля, які використовуються WHERE (у порядку вибірковості)
  • Поля, використовувані в ЗАМОВЛЕННІ ПО
  • Додайте інші поля (якщо потрібно), щоб скласти індекс покриття

Тож для вашого прикладу:

SELECT [id], [name], [customerId], [dateCreated]
   FROM Representatives WHERE customerId=1 
   ORDER BY dateCreated

Я, мабуть, спроектував би індекс на (CustomerID, dateCreate) ВКЛЮЧИТИ (id, ім'я). Цей індекс покриття означає, що запит ніколи не повинен потрапляти в оригінальну таблицю, значно покращуючи продуктивність.

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


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