查询索引视图时的 WHERE 子句性能

Posted

技术标签:

【中文标题】查询索引视图时的 WHERE 子句性能【英文标题】:WHERE Clause Performance While Querying an Indexed View 【发布时间】:2014-07-17 20:31:12 【问题描述】:

我使用如下代码(简化)创建了一个索引视图(以节省非常耗时的聚合时间):

CREATE VIEW vCosts WITH SCHEMABINDING AS
SELECT   ProjectID
         ,YEAR(Date) AS Year
         ,SUM(Cost) AS YearlyCost
FROM     dbo.DailyAssignments
GROUP BY ProjectID
         ,YEAR(Date)

CREATE UNIQUE CLUSTERED INDEX IX_vCosts ON vCosts (Year, ProjectID)

在此视图上执行 SELECT * 需要一秒钟。但是以下查询需要 30 秒(如果包括更多年份,则更糟):

SELECT *
FROM   vCosts
WHERE  Year = 2001

执行计划表明它实际上使用的是底层表而不是视图(更准确地说,它似乎使用的是 DailyAssignments 表的聚集主键而不是视图的索引)。视图上的 SELECT * 按预期使用索引。

我在其他领域没有同样的问题。以下也使用视图的索引并在不到一秒的时间内完成:

SELECT *
FROM   vCosts
WHERE  ProjectID = 1

谁能帮我理解发生了什么?

【问题讨论】:

【参考方案1】:

尝试在查看后添加WITH (NOEXPAND)。我也有这个问题。

SELECT *
FROM   vCosts WITH (NOEXPAND)
WHERE  ProjectID = 1

当为视图指定 NOEXPAND 时,查询优化器会考虑 使用视图上定义的任何索引。 NOEXPAND 用 可选的 INDEX() 子句强制查询优化器使用 指定的索引。只能为索引视图指定 NOEXPAND 并且不能为未编入索引的视图指定。

来源http://technet.microsoft.com/en-us/library/ms181151(v=sql.105).aspx

【讨论】:

成功了,谢谢!但为什么这是必要的?您能否将我引向我可以阅读的来源,以了解为什么优化器会选择在我的案例中扩展视图(使用 YEAR(date))?

以上是关于查询索引视图时的 WHERE 子句性能的主要内容,如果未能解决你的问题,请参考以下文章

挽救数据库性能的30条黄金法则

挽救数据库性能的30条黄金法则

mysql性能优化30条

为啥将 WHERE 子句放在视图之外的性能很差

sql server查询性能where子句

关于MySQL查询优化