У меня есть база данных SQL Server, где запросы выполняются довольно медленно, и есть много блокировок и блокировок.
Когда я смотрю на отсутствующие индексы DMV и планы запросов, никаких предложений нет.
Это почему?
источник
У меня есть база данных SQL Server, где запросы выполняются довольно медленно, и есть много блокировок и блокировок.
Когда я смотрю на отсутствующие индексы DMV и планы запросов, никаких предложений нет.
Это почему?
Мы рассмотрим несколько причин более подробно, а также поговорим о некоторых общих ограничениях этой функции.
Во- первых, из: Ограничения по пропавшим без индексов Характеристика :
- Он не определяет порядок использования столбцов в индексе.
Как отмечено в этом разделе «Вопросы и ответы»: как SQL Server определяет порядок расположения столбцов в пропущенных запросах индекса? порядок столбцов в определении индекса определяется предикатом равенства и неравенства, а затем порядковым номером столбца в таблице.
Там нет догадок о селективности, и может быть лучший доступный порядок. Это ваша работа, чтобы понять это.
Специальные индексы
Отсутствующие запросы индекса также не охватывают «специальные» индексы, такие как:
Пропущенные ключевые столбцы индекса создаются из столбцов, используемых для фильтрации результатов, например, в:
Отсутствующий индекс Включенные столбцы создаются из столбцов, необходимых для запроса, например, в:
Даже если довольно часто столбцы, по которым вы упорядочиваете или группируете, могут быть полезны в качестве ключевых столбцов. Это восходит к одному из ограничений:
- Он не предназначен для тонкой настройки конфигурации индексации.
Например, этот запрос не зарегистрирует отсутствующий запрос индекса, даже если добавление индекса в LastAccessDate предотвратит необходимость сортировки (и разлива на диск).
SELECT TOP (1000) u.DisplayName
FROM dbo.Users AS u
ORDER BY u.LastAccessDate DESC;
Так же как и этот групповой запрос по местоположению.
SELECT TOP (20000) u.Location
FROM dbo.Users AS u
GROUP BY u.Location
Ну да, но это лучше, чем ничего. Думайте о пропущенных запросах на индекс как плачущего ребенка. Вы знаете, что есть проблема, но вы, взрослый человек, должны выяснить, что это за проблема.
Расслабься, Бако. Мы добираемся туда.
Если вы включите 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);
Первый план тривиален, и запрос не отображается. Могут быть случаи, когда ошибки мешают отсутствующим индексам появляться в планах запросов; однако они обычно более надежно регистрируются в отсутствующих индексных DMV.
Предикаты, в которых оптимизатор не сможет эффективно использовать индекс, даже с индексом, могут помешать их регистрации.
Вещи, которые обычно не SARGable:
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;
План - это простой поиск ...
Но поскольку ведущий ключевой столбец предназначен для менее избирательного предиката, мы заканчиваем тем, что выполняем больше работы, чем должны:
Таблица «Посты». Сканирование 13, логическое чтение 136890
Если мы изменим порядок столбцов индекса ключа, мы сделаем намного меньше работы:
CREATE INDEX ix_whatever ON dbo.Posts(Score, CreationDate) INCLUDE(OwnerUserId);
И значительно меньше читает:
Таблица «Посты». Сканирование 1, логическое чтение 5
В некоторых случаях SQL Server выбирает создание индекса на лету через катушку индекса. При наличии катушки индекса отсутствующий запрос индекса не будет. Конечно, добавление индекса самостоятельно может быть хорошей идеей, но не рассчитывайте, что SQL Server поможет вам в этом разобраться.