SQL Server是否在复杂视图中传播WHERE条件?

时间:2011-08-24 22:43:03

标签: sql-server views sqlperformance

如果不清楚我对这个问题的意思,我已经完整地举了这个问题。

我做了一个视图,它连接了大约五个表的数据。这些表有大量数据,查询运行缓慢。我的问题是,如果我这样做:

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,他们参与的任何ActivitiesActivityTypeLocation。虽然这种设置并不是非常复杂,但你可以看到,如果每个实体都有数万个实体可能需要很长时间才能执行。

视图可能是这样的:

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字段?

3 个答案:

答案 0 :(得分:3)

通常,优化器将使用aplomb处理此问题,但随着查询和隐含子查询变得越来越复杂,优化器选择正确执行路径的可能性也会相应减少。通过在表上添加更多索引或者将要检查的表上的索引非常相似,可能会加剧这种情况。

作为一般规则,我试图阻止加入观点,我强烈反对创建由其他观点组成的观点。

答案 1 :(得分:2)

这称为谓词推送。

SQL Server通常很擅长这一点,尽管存在一些存在问题的构造(例如,参见this article的最后部分)。

检查执行计划以查看谓词的应用位置。

答案 2 :(得分:1)

引擎会做任何它认为最快的事情。如果您已将该字段编入索引,并且您的JOIN密钥都已编入索引,则可能首先运行或不运行该过滤器。

如果WHERE子句更昂贵(即无索引),它实际上可能会运行过滤器LAST - 这样就会在最小的结果集上运行昂贵的操作。

确定的唯一方法是运行查询并检查执行计划( ACTUAL 未估算)。