SQL Server 是不是在复杂视图中传播 WHERE 条件?
Posted
技术标签:
【中文标题】SQL Server 是不是在复杂视图中传播 WHERE 条件?【英文标题】:Does SQL Server propagate WHERE conditions in complex views?SQL Server 是否在复杂视图中传播 WHERE 条件? 【发布时间】:2011-08-24 22:43:03 【问题描述】:我已经用一个完整的例子来跟踪这个问题,以防我不清楚我的意思。
我制作了一个视图,它连接了来自大约五个表的数据。这些表有大量数据,查询运行缓慢。我的问题是,如果我这样做:
SELECT * FROM myView WHERE PersonID = 1000
SQL Server 是否“知道我的意思”并自动将该条件传播到视图中的基础连接?这样它就不会为每个人 运行,而是在正确的阶段最小化结果集。或者它会运行所有的东西然后对完整的结果集执行WHERE ID = 1000
?
一个例子
为了简化(...希望)我的意思,这里有一个伪 TSQL 场景示例:
TABLE People (
ID,
Surname,
DOB
)
TABLE Activities (
ID,
TypeID,
LocationID,
Date
)
TABLE PersonActivityInvolvements (
ID,
PersonID,
ActivityID
)
TABLE ActivityTypes (
ID,
Name
)
TABLE Locations (
ID,
Street,
City
)
所以我想要一个视图,显示所有People
、他们参与的任何Activities
、ActivityType
和Location
它发生了。尽管此设置并不十分复杂,但您可以看到,如果每个实体有数万个,则执行可能需要很长时间。
视图可能是这样的:
SELECT
*
FROM
People LEFT OUTER JOIN PersonActivityInvolvement PA
ON People.ID = PA.ID
INNER JOIN Activity
ON PA.ID = Activity.ID
INNER JOIN ActivityTypes AT
ON A.TypeID = AT.ID
INNER JOIN Locations
ON A.LocationID = Locations.ID
如果是这样的话
SELECT * FROM myView WHERE DOB >= dateAdd(YEAR, -18, getDate())
视图中的查询是否会为所有人运行,或者 SQL Server 是否知道它应该将其应用于 People.DOB
字段?
【问题讨论】:
这很容易使用 SQL Server 查询分析器进行测试。显示执行计划并查看应用于表的过滤器。如果它显示应用的 where 条件,则它是可传递的。 【参考方案1】:这称为谓词推送。
SQL Server 通常在这方面做得很好,尽管有些结构存在问题(例如,请参阅this article 的最后部分)。
检查执行计划以查看谓词的应用位置。
【讨论】:
【参考方案2】:通常,优化器会从容处理这个问题,但随着查询和隐含子查询变得越来越复杂,优化器选择正确执行路径的机会会相应减少。如果在表上设置更多索引,或者在要检查的表上设置非常相似的索引,则会加剧这种情况。
作为一般规则,我尽量不鼓励加入视图,并且强烈反对创建由其他视图组成的视图。
【讨论】:
【参考方案3】:引擎会做它认为最快的任何事情。如果您已将该字段编入索引,并且您的 JOIN
键都已编入索引,则它可能会或可能不会首先运行该过滤器。
如果WHERE
子句更昂贵(即未索引),它实际上可能会运行过滤器 LAST - 这样昂贵的操作会在最小的结果集上运行。
唯一确定的方法是运行查询并检查执行计划(ACTUAL 未估计)。
【讨论】:
以上是关于SQL Server 是不是在复杂视图中传播 WHERE 条件?的主要内容,如果未能解决你的问题,请参考以下文章
在没有索引视图的情况下,在 SQL Server 中创建复杂视图的最佳方法是啥?
在 Sql Server 2008 中索引视图是不是实际上复制了原始数据?