为什么结合3个单独查询的SQL查询运行得慢得多?

时间:2012-06-21 12:19:14

标签: sql-server sql-server-2008 tsql stored-procedures

我正在编写一个查询,随后我将分析SQL Profiler跟踪以监控查询的性能和速度。

在执行此操作时,我注意到如果我在同一个表上运行3个不同的选项,这些比在WHERE子句中使用OR的一个select中运行它们要快得多。

A)

SELECT * FROM navigation_trees nt  INNER JOIN contents c ON c.navigation_tree_id = nt.id WHERE nt.id = @NodeID

SELECT * FROM navigation_trees nt INNER JOIN contents c ON c.navigation_tree_id = nt.id WHERE nt.id = @ParentID

SELECT * FROM navigation_trees nt INNER JOIN contents c ON c.navigation_tree_id = nt.id WHERE nt.id IN (SELECT id FROM @ChildrenIDS)

B)

SELECT * FROM navigation_trees nt  INNER JOIN contents c ON c.navigation_tree_id = nt.id 
    WHERE 
        nt.id = @NodeID OR
        nt.id = @ParentID OR
        nt.id IN (SELECT id FROM @ChildrenIDS)

以下是两个查询的Profiler读数:

CPU | Reads | Writes | Duration(ms)

A) 15 | 1095 | 0 | 26

B) 531 | 456139 | 0 | 541

你能解决一些问题吗?

非常感谢。

2 个答案:

答案 0 :(得分:3)

三个选项只有三个选项,一个由OR加入的具有三个条件的选项实际上是选择加上删除重复项的额外成本。

如果您确定永远不会有重复项,请考虑使用UNION ALL而不是OR。或者当然,这是一个非常一般的建议。在仅为了提高性能而调整查询时,请始终参考执行计划,以了解特定的建议是否适用于您的方案。

答案 1 :(得分:2)

我同意大卫的意见,但想把代码示例放进去;那些或者可能是一个杀手。我教新开发人员的一个基本规则是,如果你需要一个或者你需要一个工会;这通常与过滤器早期过滤器的其他基本规则相关。对每个连接进行过滤的查询比在where子句中运行的过滤器更快,因为优化器可以看到更好的路径来减少数据。

您的查询可能会像这样工作或需要其他全部联盟。

Select
    *
From
(
    SELECT * 
    FROM 
        navigation_trees nt  
    WHERE 
        nt.id = @NodeID 

    union 
    SELECT 
        * 
    FROM 
        navigation_trees nt  
    WHERE 
        nt.id = @ParentID 

    union 
    SELECT 
        * 
    FROM 
        navigation_trees nt  
    WHERE
        nt.id IN (SELECT id FROM @ChildrenIDS)

) nt

INNER JOIN 
    contents c 
ON 
    c.navigation_tree_id = nt.id