代码之家  ›  专栏  ›  技术社区  ›  FlySwat

使用奇怪的查询优化器行为连接SQLServer中的视图

  •  6
  • FlySwat  · 技术社区  · 15 年前

    我有一个复杂的视图,我用它来拉一个主键列表,这些主键指示在两个时间点之间修改过的表中的行。

    此视图必须查询13个相关表,并查看changelog表以确定实体是否“脏”。

    即使进行了所有这些操作,也要执行一个简单的查询:

    select * from vwDirtyEntities;
    

    只需2秒钟。

    但是,如果我把它改成

    select
        e.Name
    from 
        Entities e 
             inner join vwDirtyEntities de
                 on e.Entity_ID = de.Entity_ID
    

    这需要1.5分钟。

    但是,如果我这样做:

    declare @dirtyEntities table
    (
        Entity_id uniqueidentifier;
    )
    
    insert into @dirtyEntities 
       select * from vwDirtyEntities;
    
    
    select
       e.Name
    from 
        Entities e 
            inner join @dirtyEntities de
               on e.Entity_ID = de.Entity_ID
    

    我只用2秒钟就得到了同样的结果。

    这让我相信,当连接到实体时,SQLServer正在对每行的视图进行评估,而不是构建一个查询计划,该计划涉及将上面的单个内部联接连接到视图中的其他联接。

    请注意,我希望根据此视图中的完整结果集进行联接,因为它只筛选出我内部需要的键。

    我知道我可以把它变成一个物化视图,但是这将涉及到绑定视图和它的依赖关系的模式,我不喜欢维护索引会导致的开销(这个视图只查询导出,而对底层表的写操作要多得多)。

    因此,除了使用表变量缓存视图结果之外,还有什么方法可以告诉SQL Server在评估联接时缓存视图?我尝试更改联接顺序(从视图中选择并针对实体联接),但这没有任何区别。

    视图本身也非常有效,没有优化空间。

    1 回复  |  直到 11 年前
        1
  •  5
  •   Community Mohan Dere    9 年前

    景色没有什么神奇之处。它是一个可扩展的宏。乐观者决定何时联接以将视图扩展到主查询中。

    我会在你的帖子中提到其他要点:

    • 您已经排除了索引视图。视图只有在索引时才能是离散实体

    • SQL Server永远不会自己执行RBAR查询。只有开发人员才能编写循环。

    • 没有缓存的概念:除非使用临时表,否则每个查询都使用最新的数据

    • 你坚持使用你认为非常有效的视图。但是不知道优化器是如何处理视图的 十三 桌子

    • SQL是声明性的:连接顺序通常不重要

    • 许多严肃的DB开发人员不使用视图是因为这样的限制:它们不能重用,因为它们是宏

    编辑,另一种可能性。 Predicate pushing 在SQL Server 2005上。也就是说,SQL Server无法将连接条件“深入”推送到视图中。