我想检查索引视图的查询性能。
我在Product
数据库中创建了一个包含所有列的Northwind
表的视图。在创建视图后,我在视图上添加了一个聚簇索引(因为我无法创建一个非聚集索引而没有INT)。
在我添加非聚集索引之前,我检查此查询执行计划和统计信息:
SELECT [ProductName]
,[QuantityPerUnit]
,[UnitPrice]
,[UnitsInStock]
,[UnitsOnOrder]
,[ReorderLevel]
,[Discontinued]
FROM [Northwind].[dbo].[test_IndexedView]
WHERE UnitPrice = 21.35
然后我创建了一个索引:
CREATE NONCLUSTERED INDEX [idx_Unitp] ON [dbo].[test_IndexedView]
(
[UnitPrice] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
然后我再次执行该查询但没有任何改变。执行计划中没有不在统计中。
问题在哪里?如何通过索引视图提高性能?编辑1) 我创建了一个视图:
CREATE VIEW [dbo].[indexView]
WITH SCHEMABINDING
AS
SELECT ProductName, SupplierID, CategoryID, QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, Discontinued, ReorderLevel
FROM dbo.Products
GO
然后当我想在其上创建一个'非聚集索引'时就像这样:
CREATE NONCLUSTERED INDEX [idx_Unitp] ON [dbo].[IndexView]
(
[UnitPrice] ASC
)
我收到此错误:
Ms 1940,Level 16,State 1,Line 1
无法在视图'dbo.IndexView'上创建索引。它没有唯一的聚簇索引。
所以我不得不创建一个聚集索引。
索引之前和之后的执行计划都是Index Scan
SELECT @@VERSION
的结果是:
Microsoft SQL Server 2008(SP2) - 10.0.4000.0(Intel X86)
2010年9月16日20:09:22版权所有(c)1988-2008 Microsoft Corporation
Windows NT 6.1上的企业版(Build 7600:)
答案 0 :(得分:2)
由于您从表中选择了7列,并且索引本身只包含UnitPrice
,因此SQL Server查询优化器仍然认为扫描比使用索引查找价格更有效然后必须对找到的每一行进行密钥查找以获取其他列。
我几乎敢打赌,如果你包含你索引中的其他列就像这样
CREATE NONCLUSTERED INDEX [idx_Unitp]
ON [dbo].[test_IndexedView] ([UnitPrice] ASC)
INCLUDE(ProductName, QuantityPerUnit, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued)
然后将使用该索引 - 几乎可以肯定。
实际使用非聚集索引的要求非常严格 - 远远超过大多数人最初会相信的要求。选择性必须非常高 - 有时小于1% - 甚至可以考虑指数。此外,返回的总行数(以及获取其余数据所需的键查找总数)需要很小。
你最好的选择是拥有覆盖索引 - 一个索引,其中包含满足查询的所有信息(所需的所有列) - 在这种情况下,NC索引的可能性是使用量显着增加。
答案 1 :(得分:1)
你说“我被迫创建一个聚集索引。”但是不要给出定义。由于视图上的聚簇索引必须是唯一的,我将ProductID
添加到视图定义并假设
CREATE UNIQUE CLUSTERED INDEX [idx_Unitp] ON [dbo].[IndexView]
(
[UnitPrice] ASC, ProductID ASC
)
然后我在基表上扫描时看到的与你相同
除非我在计划确实在视图上显示搜索时将查询更改为使用FROM [Northwind].[dbo].[IndexView] WITH (NOEXPAND)
。
原因是explained here。初始查询得到一个简单的计划,仅在0.0033667
计算成本。在获得索引视图匹配之前,优化器会选择此计划。
无论如何,这不是对索引视图的良好使用。直接在基表上创建索引会更好
CREATE NONCLUSTERED INDEX ixNoView
ON dbo.Products (UnitPrice)
INCLUDE ( ProductName,
QuantityPerUnit,
UnitsInStock,
UnitsOnOrder,
Discontinued,
ReorderLevel)
这比视图上的聚簇索引要窄,因为它只有7列而不是10列,以及避免索引视图匹配的问题,并且对于其他开发人员来说更容易被发现。
现在使用非索引视图
CREATE VIEW [dbo].[nonIndexedView]
AS
SELECT ProductName,
SupplierID,
CategoryID,
QuantityPerUnit,
UnitPrice,
UnitsInStock,
UnitsOnOrder,
Discontinued,
ReorderLevel,
ProductID
FROM dbo.Products
查询
SELECT [ProductName]
,[QuantityPerUnit]
,[UnitPrice]
,[UnitsInStock]
,[UnitsOnOrder]
,[ReorderLevel]
,[Discontinued]
FROM dbo.nonIndexedView
WHERE UnitPrice = 21.35
显示索引搜索