简而言之
 
,查询优化器选择索引视图索引时会考虑哪些因素?  
对我来说,索引视图似乎无视我对Optimizer如何选择索引的理解。我以前看过这个问题,但是OP不太受欢迎。 我确实在寻找路标,但是我将伪造一个伪示例,然后发布带有大量DDL,输出和示例的真实示例。
假设我使用的是Enterprise 2008+,请理解
with(noexpand)
伪示例
以这个伪示例为例:我创建一个具有22个联接,17个过滤器和一个马戏团小马的视图,该马戏小马穿过一千万个行表。这种观点很昂贵(是的,用大写字母E)可以实现。我将对SCHEMABIND进行索引并为视图建立索引。然后一个   SELECT a,b FROM AnIndexedView WHERE theClusterKeyField <  84。在Optimizer逻辑中,我无法进行底层联接。   
结果:
- 没有提示:4825读取720行,在76ms内读取47 cpu,估计的子树开销为0.30523。
- 使用提示:17次读取,720行,4 ms内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(Build 9200:)上的Microsoft Corporation Enterprise Edition(64位)(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行输出
Profiler输出
 
前4行没有提示。底部的4行使用提示。  
执行计划
GitHub Gist的两个SQLPlan格式的执行计划
没有提示执行计划-为什么不使用我给您的SQL先生的聚簇索引?它聚集在3个过滤器字段上。试试吧,您可能会喜欢。

使用提示时的简单计划。


