Коротко
Які фактори враховують вибір запиту оптимізатора на індекс індексованого перегляду?
Для мене, здається, індексовані подання не піддаються тому, що я розумію щодо того, як оптимізатор вибирає індекси. Я вже бачив, як це запитували раніше , але ОП не надто добре сприйняли. Я дійсно шукаю путівники , але буду придумувати псевдоприклад, а потім публікувати реальний приклад з великою кількістю DDL, вихідних даних, прикладів.
Припустимо, я використовую Enterprise 2008+, зрозумійте
with(noexpand)
Приклад псевдо
Візьмемо цей псевдоприклад: я створюю представлення з 22 приєднаннями, 17 фільтрами та цирковим поні, що перетинає купу 10 мільйонів рядкових таблиць. Цей погляд дорого реалізується (так, з великою літерою Е). Я 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. За кожною метрикою, яку я можу подумати, використовуючи індекс перегляду, набагато ефективніше. У мене немає проблеми з обнюхуванням параметрів або перекошеними даними, оскільки це скачування.
Справжній (довгий) приклад
Якщо ви не дотик мазохіст, вам, мабуть, не потрібна чи хочете читати цю частину.
Версія
Yep, підприємство.
Microsoft SQL Server 2012 - 11.0.2100.60 (X64) 10 лютого 2012 19:39:15 Авторські права (c) Microsoft Corporation Enterprise Edition (64-розрядні) на Windows NT 6.2 (Build 9200:) (Hypervisor)
Вид
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 фільтрувальних полях. Спробуйте, можливо, вам сподобається.
Простий план при використанні підказки.