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


19

У мене є таблиці Log і LogItem; Я пишу запит, щоб отримати деякі дані з обох. Є тисячі, Logsі кожен Logможе мати до 125LogItems

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

Existing Index: Non-clustered
Key Colums (LogItem): ParentLogID, DateModified, Name, DatabaseModified

Query Plan Recommendation
CREATE NONCLUSTERED INDEX [LogReportIndex]
ON [dbo].[LogItem] ([ParentLogID],[DatabaseModified])

Для розваги я створив цей новий індекс і запустив запит, і на мій подив, зараз для мого запиту потрібно зайняти ~ 1 секунду, коли до цього було 10+ секунд.

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

Примітка: Я не думаю, що це тому, що SQL Server кешує мої результати, я запустив запит приблизно 25-30 разів до того, як створив індекс, і він постійно проходив 10-15 секунд, після того, як індекс тепер стабільно ~ 1 менш.


Перш ніж створити додатковий некластеризований індекс, що показав фактичний план виконання для використання індексу?
Томас Стрінгер

Що покращує продуктивність на 100%?

@Shark Добре запитання, я не впевнений. Це моя перша ситуація налагодження виступу. Я обов'язково схоплю це, йдучи вперед. Все, що було сказано, було «пропущеним індексом», і було вказано, які поля.

@JeffO Ось що сказав SSMS: "Процесор запитів вважає, що реалізація наступного індексу може покращити вартість запиту на 100%".

Відповіді:


21

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

Це тому, що індекс - це дерево. Ви не можете ефективно вибрати всі вузли дерева де column3 = something, оскільки вони розкидані по всіх інших місцях, що належать до різних значень column1та column2. Але якщо ви знаєте column1і column2так, розміщення правої гілки в дереві - це не розум.


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

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

1
@Nate Широко, так. Деякі wheres можуть перекриватися, тому у вас може бути індекс, який добре покриває кілька wheres; або ви можете ігнорувати якусь частину whereпункту, оскільки індексація у певному стовпці все одно не допоможе (низька вибірковість); але широко, так.

@Nate Ви не хочете мати більше індексів, ніж потрібно. Кожен індекс, який повинен підтримувати SQL, додає власні накладні витрати. Якщо ви можете змінити порядок WHERE, щоб відповідати першим N стовпцям наявного індексу, це повинно вас дуже закрити, не додаючи додаткові індекси.
Той Чак Гай

1
@ChuckBlumreich Порядок стовпців у whereпунктах не важливий. Сервер завжди організовує їх, щоб найкраще використовувати існуючі індекси. Це лише питання наявності індексу, який включає всі необхідні whereстовпці в якості своїх перших стовпців.

12

Передній край індексу є те , що має значення.

Поки ваш запит буде "охоплений" передньою межею індексу, він буде ефективним. Індекси бази даних, як правило, реалізуються як B-Дерева, і структура B-Дерева диктує, що пошук повинен здійснюватися у певному порядку, тому порядок полів у складеному індексі має значення.

Якщо у вас є "дірки", наприклад, якщо ви шукаєте ParentLogIDі DatabaseModified, але маєте лише індекс {ParentLogID, DateModified, Name, DatabaseModified}, тоді {ParentLogID}ефективно використовувати лише частину індексу.

(ПРИМІТКА. Деякі СУБД можуть використовувати цю {DatabaseModified}частину за допомогою "пропустити сканування", але навіть якщо ваша СУБД робить це набагато менш ефективно, ніж звичайний доступ до індексу) .


Отже, якщо у мене є Columns (a, b, c, d, e, f)і більшість запитів - це ... WHERE A IN(...) AND B = 3мій індекс, Index(a,b,c,d)який є хорошим, але це не допомагає, якщо я маю ... WHERE A IN (...) AND D = 5, тому мій новий індекс, який я зробив, Index(a,d)настільки покращив ефективність, правда?

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