У мене є база даних SQL Server, де запити доволі повільні, і є багато блокування та блокування.
Коли я дивлюся на відсутні індекси DMV та плани запитів, немає пропозицій.
Чому так?
У мене є база даних SQL Server, де запити доволі повільні, і є багато блокування та блокування.
Коли я дивлюся на відсутні індекси DMV та плани запитів, немає пропозицій.
Чому так?
Відповіді:
Ми розглянемо кілька причин більш докладно, а також поговоримо про деякі загальні обмеження функції.
По-перше, з: Обмеження відсутніх показників :
- Він не визначає замовлення для використання стовпців в індексі.
Як зазначено в цьому запитанні: Як SQL Server визначає порядок стовпців ключів у відсутніх запитах на індекс? , порядок стовпців у визначенні індексу продиктовано предикатом рівності проти нерівності, а потім порядковим розташуванням стовпців у таблиці.
Немає здогадів про вибірковість, і може бути кращий порядок. Ваша робота розібратися в цьому.
Спеціальні покажчики
Відсутні запити на індекс також не охоплюють "спеціальні" індекси, як-от:
Відсутній стовпець ключових індексів створюється з стовпців, які використовуються для фільтрації результатів, як-от у:
Стовпці, що відсутні в індексі, генеруються із стовпців, необхідних для запиту, таких як:
Хоча досить часто стовпці, які ви замовляєте або групуєте, можуть бути корисними як ключові стовпці. Це повертається до одного з обмежень:
- Він не призначений для тонкої настройки конфігурації індексування.
Наприклад, цей запит не буде реєструвати відсутній запит на індекс, навіть якщо додавання індексу на LastAccessDate запобіжить необхідності сортування (та розсипання на диск).
SELECT TOP (1000) u.DisplayName
FROM dbo.Users AS u
ORDER BY u.LastAccessDate DESC;
Це також не запитує групування за адресою Location.
SELECT TOP (20000) u.Location
FROM dbo.Users AS u
GROUP BY u.Location
Ну так, але це краще, ніж нічого. Подумайте про відсутність запитів на індекс, як плаче дитина. Ви знаєте, що є проблема, але ви, дорослий, вирішити, що це за проблема.
Розслабся, букко. Ми туди потрапляємо.
Якщо ввімкнути TF 2330 , запити про відсутні індекси не будуть реєструватися. Щоб дізнатися, чи увімкнено це, запустіть це:
DBCC TRACESTATUS;
Перебудова індексів очистить пропущені запити на індекс. Тож перш ніж вирушати на пристрій Hi-Ho-Silver-Away, будуючи кожен індекс, вдруге прокрадеться йота фрагментації, подумайте над інформацією, яку ви очищаєте щоразу, коли це робите.
Ви також можете задуматися над тим, чому дефрагментація ваших індексів все-таки не допомагає . Якщо ви не використовуєте Columnstore .
Додавання, видалення або відключення індексу видалить усі пропущені запити щодо індексу для цієї таблиці. Якщо ви працюєте над декількома змінами індексу в одній таблиці, переконайтеся, що ви їх все сценарії, перш ніж робити будь-які.
Якщо план досить простий, а вибір доступу до індексу досить очевидний, а вартість досить низька, ви отримаєте тривіальний план.
Це фактично означає, що оптимізатор не міг приймати рішення на основі витрат.
Via Paul White :
Деталі того, які типи запитів можуть отримати користь від 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 допоможе вам розібратися.