我有一个运行速度很慢的查询(见下文)。在寻找改进方法时,我们发现如果我们将LEFT OUTER JOIN替换为LEFT HASH JOIN,查询的运行速度会快十倍
结果似乎是一样的。是吗?在什么情况下它不会返回相同的结果?有什么区别?在运行 LEFT HASH JOIN 而不是 LEFT OUTER JOIN 时,我应该注意什么?
查询中的[ABC].[ExternalTable]表是我添加为外部表的不同服务器上的视图
SELECT t.foo, t.bar, t.data
FROM [dbo].[Table] as t
LEFT OUTER JOIN [ABC].[ExternalTable] as s ON s.foo = t.foo and s.bar = t.bar and s.data = t.data
WHERE s.foo is null and s.bar IS NULL and s.data IS NULL
从语义上讲,这两个查询是相同的。
LOOP
vs只是告诉 SQL Server使用HASH
哪个选项来返回结果。如果您在不使用LOOP
or的情况下运行查询HASH
,SQL Server 可能会选择其中任何一个选项,具体取决于它认为性能最佳的选项。这两个选项按设计返回相同的结果。稍微不同1,在这种情况下,关键字HASH
和LOOP
是所谓的连接提示,是 Transact-SQL 中的三种提示之一。更让您感到困惑的是,您还可以将连接提示指定为查询提示,尽管两种情况下的效果不一定相同。请注意,提供这些类型的连接提示意味着FORCE ORDER
提示,它指定在查询优化期间保留查询语法指示的连接顺序(有关更多详细信息,请参见下面的 Paul 回答)。SQL Server 使用查询中每个表的统计信息
JOIN
来对 T-SQL 查询语句中的每个表进行何种物理操作做出明智的选择。在这种情况下,由于
[ExternalTable]
是通过链接服务器引用的视图,SQL Server 可能希望表中有 1 行 - 即它不知道需要多少行。您可以向查询添加连接提示以强制进行合并连接,也可以简单地将行从
[ExternalTable]
带有聚集索引的本地 #temp 表中复制,然后针对它运行查询。哈希连接的完整语法是:
join 语句中的版本
HASH
允许 SQL Server 选择连接类型,在您的特定情况下,它很可能选择 LOOP 连接,您可以强制使用:我通常不建议指定连接类型,因为大多数时候 SQL Server 非常有能力选择最合适的连接运算符样式。
1 - 感谢 Andriy 的措辞。
我只想在这里添加一些其他答案和评论:
您正在将苹果与橙子进行比较。
OUTER 是一个逻辑连接运算符。它指定您要保留行的一侧。因此需要说左或右。可以省略 OUTER 这个词,意思是 LEFT JOIN 与 LEFT OUTER JOIN 相同。
HASH 是 SQL Server 的指令,指定如何执行您要求的任何连接(例如左连接)。我们通常避免提示,让优化器决定如何做。反过来,优化器依赖于诸如统计数据之类的东西来尝试提出执行您所要求的最佳方法。覆盖优化器的一个缺点是优化器在事情发生变化时调整的自由度较小,例如其中一个表中有更多数据,或者您添加或删除了索引。
所以,说 LEFT HASH JOIN 和说 LEFT OUTER HASH JOIN 是一样的。OUTER 这个词是可选的。
是的。使用类似的连接提示
LEFT HASH JOIN
会强制查询中指定的表的连接顺序。它强制优化器以文本顺序连接表,就像您也添加了一样OPTION (FORCE ORDER)
。使用连接提示与 具有所有相同的效果
FORCE ORDER
,包括禁用聚合的重新定位和引入部分聚合。对连接提示要格外小心。它们对查询优化器的限制比大多数人意识到的要多得多。