Mar*_*uth 6 performance join sql-server
我养成了将连接条件与其他附加条件分开的习惯。不过我理解逻辑执行顺序是:
where
如果我在子句中而不是子句中添加附加条件,是否会对性能产生不利影响join
?或者这通常是在查询优化阶段得到简化和同等处理的部分?
以下是两个简单的示例查询,它们都返回相同的计划:
USE StackOverflow2010;
-- additional filters in where clause
SELECT TOP 500 p.id
FROM dbo.Posts p
INNER JOIN dbo.Votes v ON p.id = v.PostId
WHERE
v.VoteTypeId = 2
ORDER BY p.id
;
-- all criteria in on clause
SELECT TOP 500 p.id
FROM dbo.Posts p
INNER JOIN dbo.Votes v ON p.id = v.PostId AND v.VoteTypeId = 2
ORDER BY p.id
;
Run Code Online (Sandbox Code Playgroud)
我想补充一点,如果我编写较长的分析语句,通常跨越 100 行以上(格式化),我会尝试尽快减少结果集,通常使用派生表,并在到达连接之前添加一个额外的位置。
Jus*_*ave 13
几乎任何“我以 x 方式或 y 方式写一些东西重要吗”的问题只能回答“也许”。
优化器必须考虑大量潜在的连接路径和查询计划,并且他们没有太多时间来制定计划。这意味着他们最终会使用大量启发式方法来尽早修剪潜在的计划树,而不是充分考虑每个可能的查询计划。因此,对查询文本的微小更改可能会导致优化器修剪计划树的方式发生一些变化,并最终生成不同的计划。是否可能在很大程度上取决于您的查询——将少量表连接在一起的系统,其中统计信息告诉优化器存在一个明显的驱动表,并且显然应该对下一个表进行嵌套循环连接,这可能会表现不同与将数十个大型表连接在一起的系统相比,在系统中可能没有明显的驱动表,并且优化器认为许多不同的连接路径都是合理的。
最终,回答这个问题的唯一方法是逐个查询,以两种方式编写,然后查看计划是否发生变化。如果计划相同,那就没关系。如果计划发生变化,那就很重要了。至少对于该查询而言。在该版本的 SQL Server 上。具有当前的运行时统计数据和设置集。改变这些事情中的任何一个,你都必须重新评估。
实际上,这意味着您应该以最清楚地表达您的意图的方式编写查询,并让优化器完成其工作。当您分析应用程序时,您可以查看消耗最多时间的查询,并考虑是否有更有效的方法来编写这些特定查询。在绝大多数情况下,优化器都会做正确的事情。在少数情况下,优化器会执行一些低效的操作,您需要花费开发人员时间来考虑。
扩展 SMor 的评论:
简短的回答是否定的 - 当您使用 INNER JOIN 时,是否将过滤器放入联接或 where 子句中并不重要。使用外连接极大地改变了情况。和往常一样,任何性能问题都没有绝对的答案。如果两个查询在逻辑上相同,则需要检查执行计划以了解哪个更有效。
对于 OUTER JOIN,无论是在 WHERE 子句上设置条件还是在 JOIN 本身上设置条件,实际上都可以更改结果。
SELECT TOP 500 p.id
FROM dbo.Posts p
LEFT JOIN dbo.Votes v ON p.id = v.PostId AND v.VoteTypeId = 2
ORDER BY p.id
Run Code Online (Sandbox Code Playgroud)
即使帖子中没有 VoteTypeId=2 的匹配投票,也会返回帖子中的记录。
SELECT TOP 500 p.id
FROM dbo.Posts p
LEFT JOIN dbo.Votes v ON p.id = v.PostId
WHERE v.VoteTypeId = 2
ORDER BY p.id
Run Code Online (Sandbox Code Playgroud)
该WHERE
子句抵消外连接并删除 Votes 表中没有匹配项的记录。
归档时间: |
|
查看次数: |
13897 次 |
最近记录: |