2

我已经用一个完整的例子来跟踪这个问题,以防我不清楚这个问题的意思。

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

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

4

3 回答 3

3

这称为谓词推送。

SQL Server 通常在这方面做得很好,尽管有些结构存在问题(例如,请参阅本文的最后部分)。

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

于 2011-08-24T22:45:47.570 回答
3

通常,优化器会沉着应对,但随着查询和隐含的子查询变得越来越复杂,优化器选择正确执行路径的机会也会相应减少。表上有更多索引或将要检查的表上有非常相似的索引会加剧这种情况。

作为一般规则,我尽量不鼓励加入视图,并且强烈反对创建由其他视图组成的视图。

于 2011-08-24T22:51:20.413 回答
1

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

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

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

于 2011-08-24T22:47:01.697 回答