我正在编写一个查询,随后我将分析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
你能解决一些问题吗?
非常感谢。
答案 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