Почему создание этого нового индекса так улучшило производительность, когда существующий индекс включил все столбцы в новый индекс?

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 или менее.

Nate
источник
До того как вы создали дополнительный некластеризованный индекс, что показывал фактический план выполнения для использования индекса?
Томас Стрингер
Что улучшает производительность на 100%?
@ Shark Хороший вопрос, я не уверен. Это моя первая ситуация с отладкой производительности. Я обязательно поймаю это в будущем. Все, что он сказал, было «Отсутствует индекс», и он сказал, какие поля.
@JeffO Вот что сказал SSMS: «Процессор запросов оценивает, что реализация следующего индекса может повысить стоимость запроса на 100%».

Ответы:

21

Порядок столбцов в индексе важен. Если для фильтрации требуются столбцы 1 и 4 из индекса, индекс не поможет. Это полезно только при фильтрации по первым N последовательным столбцам.

Это потому, что индекс это дерево. Вы не можете эффективно выбрать все узлы дерева где column3 = something, потому что они разбросаны по всем остальным местам, принадлежащим разным значениям column1и column2. Но если вы знаете , column1и column2как хорошо, местонахождение правой ветви в дереве является не просто.

GSerg
источник
Тогда можно было бы с уверенностью предположить (в общем), что мне нужен один индекс для каждого набора «где» предложений, которые попадут в эту таблицу?
Однажды я значительно ускорил выполнение чужого запроса, просто убедившись, что он использует индекс в правильном порядке.
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