1

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

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

一个)

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)

二)

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

你能解释一下吗?

非常感谢。

4

2 回答 2

3

三选就是三选,一个三条件的选,加入的OR其实是选加上去重复的额外成本。

如果您确定永远不会有重复,请考虑使用UNION ALL而不是OR. 或者,当然,这是一个非常笼统的建议。仅出于性能考虑而调整查询时,请始终参考您的执行计划以查看特定建议是否适用于您的场景。

于 2012-06-21T12:23:19.673 回答
2

我同意大卫的观点,但想放一个代码示例;那些 Or 很可能是杀手。我教新开发人员的一个基本规则是,如果你需要一个或者你需要一个联合;这通常与过滤早期过滤的其他基本规则相关。在每个连接上过滤的查询通常比在 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 
于 2012-06-21T12:40:53.080 回答