USE AdventureWorks
GO-- 建立索引视图时, 必须满足的选项设置
SET QUOTED_IDENTIFIER, ANSI_NULLS ON
GO-- 建立视图
CREATE VIEW Sales.v_SaleOrders
WITH SCHEMABINDING   -- 索引视图要求必须具有此项
AS
SELECT 
O.OrderDate, OD.ProductID,
Revenue = SUM(OD.UnitPrice * OD.OrderQty * (1 - OD.OrderQty)),
ItemCount = COUNT_BIG(*)   -- 索引视图中必须用COUNT_BIG
FROM Sales.SalesOrderHeader O
INNER JOIN Sales.SalesOrderDetail OD
ON O.SalesOrderID = OD.SalesOrderID
GROUP BY O.OrderDate, OD.ProductID
GO
-- 在视图上建立索引
CREATE UNIQUE CLUSTERED INDEX IXUC_ProductID_OrderDate
ON Sales.v_SaleOrders(
ProductID, OrderDate)
GO-- 执行与视图相关的查询
SET SHOWPLAN_TEXT ON
GO 
SELECT * FROM Sales.v_SaleOrders --WITH(INDEX = IXUC_ProductID_OrderDate)
GO
SET SHOWPLAN_TEXT OFF
GO-- 删除演示环境
DROP VIEW Sales.v_SaleOrders
/*StmtText
----------------------------------------------------------------------------
SELECT * FROM Sales.v_SaleOrders --WITH(INDEX = IXUC_ProductID_OrderDate)(1 row(s) affected)StmtText
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  |--Parallelism(Gather Streams)
       |--Hash Match(Aggregate, HASH:([O].[OrderDate], [OD].[ProductID]), RESIDUAL:([AdventureWorks].[Sales].[SalesOrderHeader].[OrderDate] as [O].[OrderDate] = [AdventureWorks].[Sales].[SalesOrderHeader].[OrderDate] as [O].[OrderDate] AND [AdventureWorks].[Sales].[SalesOrderDetail].[ProductID] as [OD].[ProductID] = [AdventureWorks].[Sales].[SalesOrderDetail].[ProductID] as [OD].[ProductID]) DEFINE:([Expr1004]=SUM([Expr1006]), [Expr1005]=COUNT(*)))
            |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([O].[OrderDate], [OD].[ProductID]))
                 |--Hash Match(Inner Join, HASH:([O].[SalesOrderID])=([OD].[SalesOrderID]))
                      |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([O].[SalesOrderID]))
                      |    |--Clustered Index Scan(OBJECT:([AdventureWorks].[Sales].[SalesOrderHeader].[PK_SalesOrderHeader_SalesOrderID] AS [O]))
                      |--Compute Scalar(DEFINE:([Expr1006]=([AdventureWorks].[Sales].[SalesOrderDetail].[UnitPrice] as [OD].[UnitPrice]*CONVERT_IMPLICIT(money,[AdventureWorks].[Sales].[SalesOrderDetail].[OrderQty] as [OD].[OrderQty],0))*CONVERT_IMPLICIT(money,(1)-CONVERT_IMPLICIT(int,[AdventureWorks].[Sales].[SalesOrderDetail].[OrderQty] as [OD].[OrderQty],0),0)))
                           |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([OD].[SalesOrderID]))
                                |--Clustered Index Scan(OBJECT:([AdventureWorks].[Sales].[SalesOrderDetail].[PK_SalesOrderDetail_SalesOrderID_SalesOrderDetailID] AS [OD]))(9 row(s) affected)
*/

解决方案 »

  1.   

    楼主,你的代码在我这里执行出来的结果是不一样的,我的是:
      |--Clustered Index Scan(OBJECT:([AdventureWorks].[Sales].[v_SaleOrders].[IXUC_ProductID_OrderDate]))
      

  2.   


    当满足下列条件时,SQL Server 查询优化器使用索引视图: 下列会话选项均设置为 ON: 
    ANSI_NULLS
    ANSI_PADDING
    ANSI_WARNINGS
    ARITHABORT
    CONCAT_NULL_YIELDS_NULL
    QUOTED_IDENTIFIER 
    NUMERIC_ROUNDABORT 会话选项设置为 OFF。
    查询优化器查找视图索引列与查询中的元素之间的匹配,例如: 
    WHERE 子句中的搜索条件谓词
    联接操作
    聚合函数
    GROUP BY 子句
    表引用
    估计的索引使用成本是查询优化器考虑使用的所有访问机制中的最低成本。 
    查询中引用(直接或通过展开视图访问其基础表)的且与索引视图中的表引用相对应的每个表在该查询中都必须具有应用于表的相同提示集。 
    注意:在此上下文中,不管当前的事务隔离级别是什么,READCOMMITTED 和 READCOMMITTEDLOCK 提示始终被认为是不同的提示。
     
    ANSI_NULLS
    ANSI_PADDING
    ANSI_WARNINGS
    ARITHABORT
    CONCAT_NULL_YIELDS_NULL
    QUOTED_IDENTIFIER 
    NUMERIC_ROUNDABORT 会话选项设置为 OFF。
    除 SET 选项和表提示的要求外,查询优化器也使用上述规则确定表索引是否包含查询。不必在查询中指定其他内容即可使用索引视图。查询不必在 FROM 子句中显式引用索引视图,查询优化器即可使用该索引视图。如果查询所引用的基表中的列也同时存在于索引视图中,并且,查询优化器估计使用索引视图将提供最低成本的访问机制,则查询优化器会选择索引视图,其方式类似于当查询中不直接引用基表索引时选择基表索引。当视图中包含非查询所引用的列时,只要视图提供包含一个或多个查询中所指定列的最低成本选项,查询优化器即可能选择该视图。查询优化器将 FROM 子句中引用的索引视图视为标准视图。查询优化器在优化进程开始时将视图的定义展开至查询中。然后,执行索引视图匹配。可以将索引视图用于优化器选择的最终执行计划中,或该计划可以通过访问视图引用的基表来具体化由视图得到的必要数据。优化器会选择成本最低的方式。
    当我把我的环境的SET ANSI_NULLS OFF时,我的执行结果就和你一样了.
      

  3.   

    为啥会出现这种情况?我这即便加了索引提示查询的还是基础表,sql server 2005 英文标准版 sp2
      

  4.   

    无关,我的机子是DELL 双核的,具体还是否有其他原因造成,我也不清楚,以上是我知道的。
      

  5.   


    --LZ你加个上WITH (NOEXPAND) 试一下会不会用Index?SELECT * FROM Sales.v_SaleOrders WITH(NOEXPAND) 
      

  6.   


    多谢这位朋友,问题已解决,我不知道有这个表提示。现在还有两个问题1> 查询索引视图一定要加这个表提示才能直接访问该视图么?难道查询优化器认为访问基表比访问索引视图效率更高?
    2> 老大的书中说即便不直接查询索引视图,比如查询下面这段代码,查询优化器也会选择直接查询索引视图,但是在我这不行,查询的还是基础表,将相关会话选项按要求设置也不行。SELECT 
    OD.ProductID,
    Revenue = AVG(OD.UnitPrice * OD.OrderQty * (1 - OD.OrderQty))
    FROM Sales.SalesOrderHeader O
    INNER JOIN Sales.SalesOrderDetail OD
    ON O.SalesOrderID = OD.SalesOrderID
    WHERE OrderDate >= '20020101' 
    AND OrderDate < '20030101'
    GROUP BY OD.ProductID
      

  7.   

    我的是:
    |--Clustered Index Scan(OBJECT:([AdventureWorks].[Sales].[v_SaleOrders].[IXUC_ProductID_OrderDate]))我是双核的。
      

  8.   

    居然没留意到这个回复
    ------
    是版本的原因啦只有在Developer 和 Enterprise版的才不用指定NOEXPAND,其它版本统统都得手动指定NoExpand才能使用视图
    索引。