Вкратце
Какие факторы влияют на выбор оптимизатором индекса индексированного представления?
Мне кажется, что индексированные представления не поддаются пониманию того, как оптимизатор выбирает индексы. Я уже видел этот вопрос раньше , но ОП был не слишком хорошо принят. Я действительно ищу ориентиры , но я придумаю псевдо-пример, а затем опубликую реальный пример с большим количеством DDL, выводом, примерами.
Предположим, я использую Enterprise 2008+, понимаю
with(noexpand)
Пример псевдо
Возьмите этот псевдо-пример: я создаю представление с 22 объединениями, 17 фильтрами и цирковым пони, который пересекает группу из 10 миллионов строк. Это представление дорого (да, с большой буквы E), чтобы материализоваться. Я SCHEMABIND и индексировать представление. Тогда а SELECT a,b FROM AnIndexedView WHERE theClusterKeyField < 84
. В логике оптимизатора, которая ускользает от меня, выполняются базовые объединения.
Результат:
- Нет подсказки: 4825 считываний для 720 строк, 47 процессоров в течение 76 мс и предполагаемая стоимость поддерева 0,30523.
- С подсказкой: 17 операций чтения, 720 строк, 15 процессоров в течение 4 мс и приблизительная стоимость поддерева 0,007253
Так что здесь происходит? Я пробовал это в Enterprise 2008, 2008-R2 и 2012. По всем показателям, которые я могу использовать, использование индекса представления значительно эффективнее. У меня нет проблем с прослушиванием параметров или перекосом данных, так как это рекламный хоккей.
Реальный (длинный) пример
Если вы не мазохист, вам, вероятно, не нужно или вы не хотите читать эту часть.
Версия
Да, предприятие.
Microsoft SQL Server 2012 - 11.0.2100.60 (X64) 10 февраля 2012 г. 19:39:15 Авторское право (c) Microsoft Corporation Enterprise Edition (64-разрядная версия) в Windows NT 6.2 (сборка 9200:) (гипервизор)
Вид
CREATE VIEW dbo.TimelineMaterialized WITH SCHEMABINDING
AS
SELECT TM.TimelineID,
TM.TimelineTypeID,
TM.EmployeeID,
TM.CreateUTC,
CUL.CultureCode,
CASE
WHEN TM.CustomerMessageID > 0 THEN TM.CustomerMessageID
WHEN TM.CustomerSessionID > 0 THEN TM.CustomerSessionID
WHEN TM.NewItemTagID > 0 THEN TM.NewItemTagID
WHEN TM.OutfitID > 0 THEN TM.OutfitID
WHEN TM.ProductTransactionID > 0 THEN TM.ProductTransactionID
ELSE 0 END As HrefId,
CASE
WHEN TM.CustomerMessageID > 0 THEN IsNull(C.Name, 'N/A')
WHEN TM.CustomerSessionID > 0 THEN IsNull(C.Name, 'N/A')
WHEN TM.NewItemTagID > 0 THEN IsNull(NI.Title, 'N/A')
WHEN TM.OutfitID > 0 THEN IsNull(O.Name, 'N/A')
WHEN TM.ProductTransactionID > 0 THEN IsNull(PT_PL.NameLocalized, 'N/A')
END as HrefText
FROM dbo.Timeline TM
INNER JOIN dbo.CustomerSession CS ON TM.CustomerSessionID = CS.CustomerSessionID
INNER JOIN dbo.CustomerMessage CM ON TM.CustomerMessageID = CM.CustomerMessageID
INNER JOIN dbo.Outfit O ON PO.OutfitID = O.OutfitID
INNER JOIN dbo.ProductTransaction PT ON TM.ProductTransactionID = PT.ProductTransactionID
INNER JOIN dbo.Product PT_P ON PT.ProductID = PT_P.ProductID
INNER JOIN dbo.ProductLang PT_PL ON PT_P.ProductID = PT_PL.ProductID
INNER JOIN dbo.Culture CUL ON PT_PL.CultureID = CUL.CultureID
INNER JOIN dbo.NewsItemTag NIT ON TM.NewsItemTagID = NIT.NewsItemTagID
INNER JOIN dbo.NewsItem NI ON NIT.NewsItemID = NI.NewsItemID
INNER JOIN dbo.Customer C ON C.CustomerID = CASE
WHEN TM.TimelineTypeID = 1 THEN CM.CustomerID
WHEN TM.TimelineTypeID = 5 THEN CS.CustomerID
ELSE 0 END
WHERE CUL.IsActive = 1
Кластерный индекс
CREATE UNIQUE CLUSTERED INDEX PK_TimelineMaterialized ON
TimelineMaterialized (EmployeeID, CreateUTC, CultureCode, TimelineID)
Тест SQL
-- NO HINT - - - - - - - - - - - - - - -
SELECT * --yes yes, star is bad ...just a test example
FROM TimelineMaterialized TM
WHERE
TM.EmployeeID = 2
AND TM.CultureCode = 'en-US'
AND TM.CreateUTC > '9/10/2012'
AND TM.CreateUTC < '9/11/2012'
-- WITH HINT - - - - - - - - - - - - - - -
SELECT *
FROM TimelineMaterialized TM with(noexpand)
WHERE
TM.EmployeeID = 2
AND TM.CultureCode = 'en-US'
AND TM.CreateUTC > '9/10/2012'
AND TM.CreateUTC < '9/11/2012'
Результат = 11 строк вывода
Профилировщик Вывод
Верхние 4 строки без подсказки. Нижние 4 строки используют подсказку.
Планы выполнения
GitHub Gist для обоих планов выполнения в формате SQLPlan
Нет Подсказка План выполнения - почему бы не использовать кластерный индекс, который я дал вам мистер SQL? Он сгруппирован по 3 полям фильтра. Попробуйте, вам это может понравиться.
Простой план при использовании подсказки.