为什么索引视图不会提高性能?

时间:2016-04-01 16:49:31

标签: sql sql-server tsql

我正在测试索引视图的性能。以下是我使用的代码。 我正在使用AdventureWorks2012数据库。

- 创建测试表

 SELECT * 
    INTO Person.Person_Test
    FROM [Person].[Person]
    go
    SELECT * 
    INTO Person.PersonPhone_Test
    FROM [Person].[PersonPhone]
    go
    SELECT * 
    INTO Person.BusinessEntityAddress_Test
    FROM [Person].BusinessEntityAddress
    go
    SELECT * 
    INTO Person.Address_Test
    FROM [Person].Address
    go

SET STATISTICS IO ON
SET STATISTICS TIME ON

- 在表格上创建索引

CREATE CLUSTERED INDEX Person1 ON Person.Person_Test (BusinessEntityID);
CREATE CLUSTERED INDEX PersonPhone1 ON Person.PersonPhone_Test (BusinessEntityID);
CREATE CLUSTERED INDEX BusEntity1 ON Person.BusinessEntityAddress_Test (BusinessEntityID);
CREATE INDEX BusEntity2 ON Person.BusinessEntityAddress_Test (AddressId);
CREATE CLUSTERED INDEX AddressInd1 ON Person.Address_Test (AddressId);

- 根据四个表创建视图

 CREATE VIEW My_View WITH SCHEMABINDING AS
      SELECT P.BusinessEntityID,P.FirstName,P.LastName, PH.PhoneNumber,PH.PhoneNumberTypeID,BU.AddressID,AD.AddressLine1
      FROM Person.Person_Test P
      INNER JOIN Person.PersonPhone_Test PH
      ON P.BusinessEntityID=PH.BusinessEntityID
      INNER JOIN Person.BusinessEntityAddress_Test BU
      ON P.BusinessEntityID=BU.BusinessEntityID
      INNER JOIN Person.Address_Test AD
      ON BU.AddressID=AD.AddressID
      WHERE P.BusinessEntityID BETWEEN 50 AND 10000 AND AD.AddressID BETWEEN 100 AND 1000
    GO

然后我测试没有索引的性能(Query1)

--Test regular view 
SELECT BusinessEntityID,LastName,PhoneNumber,AddressID, AddressLine1
FROM My_View
WHERE BusinessEntityID between 50 and 200

我得到的信息是:

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 8 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

(91 row(s) affected)
Table 'Address_Test'. Scan count 91, logical reads 185, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'PersonPhone_Test'. Scan count 91, logical reads 184, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Person_Test'. Scan count 91, logical reads 286, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'BusinessEntityAddress_Test'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 1 ms.

然后我在视图上添加索引

CREATE UNIQUE CLUSTERED INDEX idx_MyView ON My_View(BusinessEntityID);
go

但是,如果我重新运行上面的查询1,我收到相同的消息。 我还在这里附上执行计划。无论视图是索引还是未编入索引,执行计划都是相同的。 enter image description here enter image description here

我错过了什么吗?为视图添加索引后为什么性能相同?

2 个答案:

答案 0 :(得分:2)

视图条件比查询条件更具限制性。该视图的数据少于所需数据。

WHERE P.BusinessEntityID BETWEEN 50 AND 10000 AND AD.AddressID BETWEEN 100 AND 1000

VS

WHERE BusinessEntityID between 50 and 200

即使这是固定索引视图匹配非常脆弱并且可能失败。您可能需要使用NOEXPAND强制它。

答案 1 :(得分:1)

感谢@mxix。 NOEXPAND给了我一个新消息。

SELECT BusinessEntityID,LastName,PhoneNumber,AddressID, AddressLine1
FROM My_View WITH (NOEXPAND)
WHERE BusinessEntityID between 50 and 200;
go

消息:

 SQL Server parse and compile time: 
       CPU time = 0 ms, elapsed time = 0 ms.
    SQL Server parse and compile time: 
       CPU time = 0 ms, elapsed time = 0 ms.

(91 row(s) affected)
Table 'My_View'. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

enter image description here @FLICKER也是正确的,优化器非常聪明。

@usr指出了关键点。如果我使用

SELECT BusinessEntityID,LastName,PhoneNumber,AddressID, AddressLine1
FROM My_View 
WHERE BusinessEntityID between 100 and 20000;
go

我不需要指定NOEXPAND。 SQL Server将自动在视图中使用索引。

SQL Server parse and compile time: 
   CPU time = 15 ms, elapsed time = 16 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

(129 row(s) affected)
Table 'My_View'. Scan count 1, logical reads 5, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.