간단히 말해서
어떤 요소가 쿼리 최적화 프로그램의 인덱스 뷰 인덱스 선택을 쿼리합니까?
나에게 인덱싱 된 뷰는 옵티마이 저가 인덱스를 선택하는 방법에 대해 이해하는 것을 무시하는 것 같습니다. 전에 요청한 것을 보았지만 OP가 너무 잘 수신되지 않았습니다. 나는 실제로 guideposts를 찾고 있지만 의사 예제를 작성 한 다음 많은 DDL, 출력, 예제와 함께 실제 예제를 게시 할 것입니다.
Enterprise 2008+를 사용한다고 가정하고 이해
with(noexpand)
의사 예
이 의사 예제를 보자. 22 조인, 17 필터 및 1 천만 행 테이블을 가로 지르는 서커스 포니로 뷰를 만듭니다. 이 견해는 실현하기에는 비싸다 (자본 E와 함께). SCHEMABIND하고 뷰를 인덱싱하겠습니다. 그런 다음 SELECT a,b FROM AnIndexedView WHERE theClusterKeyField < 84
. 나를 방해하는 Optimizer 로직에서 기본 조인이 수행됩니다.
결과:
- 힌트 없음 : 720 개 행에 대해 4825 개의 읽기, 76ms에 걸쳐 47 개의 CPU 및 0.30523의 예상 하위 트리 비용.
- 힌트 : 읽기 17 회, 행 720 개, 4ms 동안 15 CPU, 예상 하위 트리 비용 0.007253
무슨 일이야? Enterprise 2008, 2008-R2 및 2012 에서 사용해 보았습니다 . 뷰의 인덱스를 사용하는 것으로 생각할 수있는 모든 메트릭이 훨씬 더 효율적입니다. 매개 변수 스니핑 문제가 있거나 데이터가 왜곡되어 있습니다.
실제 (긴) 예
당신이 터치 마조히즘이 아니라면 아마도이 부분을 읽거나 읽을 필요는 없습니다.
엔터프라이즈 버전 .
Microsoft SQL Server 2012-11.0.2100.60 (X64) 2012 년 2 월 10 일 19:39:15 저작권 (c) Windows NT 6.2 (빌드 9200 :)의 Microsoft Corporation Enterprise Edition (64 비트) (하이퍼 바이저)
보기
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 줄은 힌트를 사용하고 있습니다.
실행 계획
SQLPlan 형식으로 모두 실행 계획에 대한 GitHub의 요점
힌트 실행 계획 없음-SQL 씨에게 제공 한 클러스터형 인덱스를 사용하지 않는 이유는 무엇입니까? 3 개의 필터 필드에 클러스터되어 있습니다. 시도해보십시오. 마음에들 것입니다.
힌트를 사용할 때 간단한 계획.