Почему SQL Server не имеет отсутствующих запросов на индексирование в DMV или планах запросов?

14

У меня есть база данных SQL Server, где запросы выполняются довольно медленно, и есть много блокировок и блокировок.

Когда я смотрю на отсутствующие индексы DMV и планы запросов, никаких предложений нет.

Это почему?

Эрик Дарлинг
источник

Ответы:

17

Есть много причин, по которым у вас может не быть пропущенных запросов на индекс!

Мы рассмотрим несколько причин более подробно, а также поговорим о некоторых общих ограничениях этой функции.

Общие ограничения

Во- первых, из: Ограничения по пропавшим без индексов Характеристика :

  • Он не определяет порядок использования столбцов в индексе.

Как отмечено в этом разделе «Вопросы и ответы»: как SQL Server определяет порядок расположения столбцов в пропущенных запросах индекса? порядок столбцов в определении индекса определяется предикатом равенства и неравенства, а затем порядковым номером столбца в таблице.

Там нет догадок о селективности, и может быть лучший доступный порядок. Это ваша работа, чтобы понять это.

Специальные индексы

Отсутствующие запросы индекса также не охватывают «специальные» индексы, такие как:

  • кластерный
  • отфильтрованный
  • Разделенный
  • Сжатый
  • XML-редактор
  • Пространственно-й изд
  • Columnstore-д
  • Индексированный просмотр

Какие столбцы считаются?

Пропущенные ключевые столбцы индекса создаются из столбцов, используемых для фильтрации результатов, например, в:

  • JOIN и
  • ГДЕ оговорка

Отсутствующий индекс Включенные столбцы создаются из столбцов, необходимых для запроса, например, в:

  • ВЫБРАТЬ
  • ГРУППА ПО
  • СОРТИРОВАТЬ ПО

Даже если довольно часто столбцы, по которым вы упорядочиваете или группируете, могут быть полезны в качестве ключевых столбцов. Это восходит к одному из ограничений:

  • Он не предназначен для тонкой настройки конфигурации индексации.

Например, этот запрос не зарегистрирует отсутствующий запрос индекса, даже если добавление индекса в LastAccessDate предотвратит необходимость сортировки (и разлива на диск).

SELECT TOP (1000) u.DisplayName
FROM dbo.Users AS u
ORDER BY u.LastAccessDate DESC;

NUTS

Так же как и этот групповой запрос по местоположению.

SELECT TOP (20000) u.Location
FROM dbo.Users AS u
GROUP BY u.Location

NUTS

Это звучит не очень полезно!

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

Вы все еще не сказали мне, почему у меня их нет, хотя ...

Расслабься, Бако. Мы добираемся туда.

Флаги трассировки

Если вы включите TF 2330 , пропущенные запросы на индексирование не будут регистрироваться. Чтобы узнать, включено ли это, запустите:

DBCC TRACESTATUS;

Индекс перестраивается

Перестройка индексов очистит пропущенные запросы индекса. Поэтому, прежде чем приступить к Hi-Ho-Silver-Away перестройке каждого индекса за секунду, когда проникает йота фрагментации, подумайте об информации, которую вы очищаете каждый раз, когда вы делаете это.

Вы также можете подумать о том, почему дефрагментация ваших индексов не помогает . Если вы не используете Columnstore .

Добавление, удаление или отключение индексов

Добавление, удаление или отключение индекса очистит все отсутствующие запросы индекса для этой таблицы. Если вы работаете с несколькими изменениями индексов в одной и той же таблице, убедитесь, что вы записали их все перед тем, как вносить какие-либо изменения.

Тривиальные Планы

Если план достаточно прост и выбор доступа к индексу достаточно очевиден, а стоимость достаточно низкая, вы получите тривиальный план.

Это фактически означает, что оптимизатор не принимал решений, основанных на затратах.

Виа Пол Уайт :

Детали того, какие типы запросов могут извлечь выгоду из Trivial Plan, часто меняются, но такие вещи, как объединения, подзапросы и предикаты неравенства, как правило, препятствуют этой оптимизации.

Когда план тривиален, дополнительные этапы оптимизации не рассматриваются, а отсутствующие индексы не запрашиваются .

Посмотрите на разницу между этими запросами и их планами :

SELECT *
FROM dbo.Users AS u
WHERE u.Reputation = 2;

SELECT *
FROM dbo.Users AS u
WHERE u.Reputation = 2
AND 1 = (SELECT 1);

NUTS

Первый план тривиален, и запрос не отображается. Могут быть случаи, когда ошибки мешают отсутствующим индексам появляться в планах запросов; однако они обычно более надежно регистрируются в отсутствующих индексных DMV.

SARGability

Предикаты, в которых оптимизатор не сможет эффективно использовать индекс, даже с индексом, могут помешать их регистрации.

Вещи, которые обычно не SARGable:

  • Столбцы в функциях
  • Столбец + SomeValue = SomePredicate
  • Столбец + AnotherColumn = SomePredicate
  • Столбец = @Variable ИЛИ @Variable IS NULL

Примеры:

SELECT *
FROM dbo.Users AS u
WHERE ISNULL(u.Age, 1000) > 1000;


SELECT *
FROM dbo.Users AS u
WHERE DATEDIFF(DAY, u.CreationDate, u.LastAccessDate) > 5000


SELECT *
FROM dbo.Users AS u
WHERE u.UpVotes + u.DownVotes > 10000000


DECLARE @ThisWillHappenWithStoredProcedureParametersToo NVARCHAR(40) = N'Eggs McLaren'
SELECT *
FROM dbo.Users AS u
WHERE u.DisplayName LIKE @ThisWillHappenWithStoredProcedureParametersToo 
      OR @ThisWillHappenWithStoredProcedureParametersToo IS NULL;

Ни один из этих запросов не зарегистрирует отсутствующие запросы индекса. Для получения дополнительной информации об этом, проверьте следующие ссылки:

У вас уже есть хороший индекс

Возьмите этот индекс:

CREATE INDEX ix_whatever ON dbo.Posts(CreationDate, Score) INCLUDE(OwnerUserId);

Это выглядит хорошо для этого запроса:

SELECT p.OwnerUserId, p.Score
FROM dbo.Posts AS p
WHERE p.CreationDate >= '20070101'
AND   p.CreationDate < '20181231'
AND   p.Score >= 25000
AND 1 = (SELECT 1)
ORDER BY p.Score DESC;

План - это простой поиск ...

NUTS

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

Таблица «Посты». Сканирование 13, логическое чтение 136890

Если мы изменим порядок столбцов индекса ключа, мы сделаем намного меньше работы:

CREATE INDEX ix_whatever ON dbo.Posts(Score, CreationDate) INCLUDE(OwnerUserId);

NUTS

И значительно меньше читает:

Таблица «Посты». Сканирование 1, логическое чтение 5

SQL Server создает индексы для вас

В некоторых случаях SQL Server выбирает создание индекса на лету через катушку индекса. При наличии катушки индекса отсутствующий запрос индекса не будет. Конечно, добавление индекса самостоятельно может быть хорошей идеей, но не рассчитывайте, что SQL Server поможет вам в этом разобраться.

NUTS

Эрик Дарлинг
источник