인덱싱 된 뷰의 클러스터형 인덱스에는 어떤 요소가 선택됩니까?


19

간단히 말해서
어떤 요소가 쿼리 최적화 프로그램의 인덱스 뷰 인덱스 선택을 쿼리합니까?

나에게 인덱싱 된 뷰는 옵티마이 저가 인덱스를 선택하는 방법에 대해 이해하는 것을 무시하는 것 같습니다. 전에 요청한 것을 보았지만 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 행의 출력

11 행의 출력-두 쿼리 모두 동일

프로파일 러 출력
상단 4 줄에는 힌트가 없습니다. 아래쪽 4 줄은 힌트를 사용하고 있습니다.

프로파일 러

실행 계획
SQLPlan 형식으로 모두 실행 계획에 대한 GitHub의 요점

힌트 실행 계획 없음-SQL 씨에게 제공 한 클러스터형 인덱스를 사용하지 않는 이유는 무엇입니까? 3 개의 필터 필드에 클러스터되어 있습니다. 시도해보십시오. 마음에들 것입니다.
힌트 없음-거대한 실행 계획

힌트를 사용할 때 간단한 계획.

힌트 사용-간단한 실행 계획


답변:


26

인덱싱 된 뷰를 일치시키는 작업은 상대적으로 비용이 많이 드는 작업 *이므로 최적화 프로그램이 다른 빠르고 쉬운 변환을 먼저 시도합니다. 저렴한 계획 (귀하의 경우 0.05 단위)을 생산하면 최적화가 일찍 종료됩니다. 베팅은 지속적인 최적화가 저장된 것보다 더 많은 시간을 소비한다는 것입니다. 옵티마이 저의 주요 목표는 '충분히 좋은'계획입니다.

뷰에서 클러스터형 인덱스를 사용 하는 것은 비용이 많이 들지 않지만 논리적 쿼리 트리를 잠재적 인 인덱싱 된 뷰와 일치시키는 프로세스는 비용이 많이들 수 있습니다. 다른 질문에 대한 주석에서 언급했듯이 쿼리의 뷰 참조는 최적화 전에 확장되므로 최적화 프로그램은 처음에 뷰에 대해 쿼리를 작성한 것을 알지 못합니다. 확장 된 트리 만 보입니다. 보기가 인라인되었습니다.)

"충분한 계획"은 옵티마이 저가 적절한 계획을 발견하고 탐색 단계에서 조기에 중지했음을 의미합니다. "TimeOut"은 현재 단계 시작시 자체적으로 '예산'으로 설정 한 최적화 단계 수를 초과했음을 의미합니다.

예산은 이전 단계에서 찾은 최상의 계획 비용을 기준으로 설정됩니다. 이러한 저비용 쿼리 (0.05)를 사용하면 예산 이동 횟수가 매우 적고 샘플 쿼리에 포함 된 조인 수를 고려한 정규 변환으로 빠르게 소진됩니다 (예 : 내부 조인을 재배 열하는 방법은 많이 있음) .

인덱싱 된 뷰 일치가 비싼 이유에 대해 더 자세히 알고 싶기 때문에 이후 최적화 단계를 위해 남겨 두거나 더 많은 비용이 드는 쿼리에 대해서만 고려되는 경우 여기 (pdf)와 여기 (citeseer ) 에 대한 두 개의 Microsoft 연구 논문이 있습니다. ).

다른 관련 요소는 최적화 단계 0 (트랜잭션 처리)에서 인덱싱 된 뷰 일치를 사용할 수 없다는 것입니다.

더 읽을 거리 :

인덱싱 된 뷰 및 통계

* Enterprise Edition (또는 동등한 버전)에서만 사용 가능

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.