TSQL - 连接表的正确顺序是什么?

时间:2012-03-29 14:34:58

标签: sql-server database tsql join join-hints

我的google-fu和so-fu在这里让我失望,所以我不妨问。

我有很多查询,其中有多个连接。

在一个查询中,我将标题/项目/详细信息一起加入,以及查找这些记录的各种信息。

加入时,我会尽量保持相关的顺序。例如:我的标题有两个查找表,所以在加入我的项目表之前我会加入那些。

这是对的吗?

在查找表之前加入更大的表是否更好?或相反亦然?

我是否应该在加入小型表时使用loop提示,并在加入openrowsets时使用merge提示?

我确信答案是“它取决于”,但有效和高效地加入的一些一般指导方针将非常有帮助。谢谢!

2 个答案:

答案 0 :(得分:12)

编辑:根据您的问题(和Kirk Woll的)评论,您应该了解order of your joins is aesthetic, and does not directly impact the resulting execution plan。查询优化器将以最有效的顺序执行连接,并在绝大多数情况下使用适当的连接操作,而不需要任何提示。

当你的连接顺序的美学出现时,这有点主观,但我会说在阅读查询时以任何顺序将你的表连在一起......如果你从@HeaderId开始,开始使用该表,然后JOIN到子表:

FROM
    Header h
    JOIN Items i ON h.HeaderId = i.HeaderId
    JOIN Details d ON i.ItemId = d.ItemId
WHERE
    h.HeaderId = @HeaderId

但是,如果您使用@DetailId开始查询,我会以相反的顺序加入。

FROM
    Details d
    JOIN Items i ON d.ItemId = i.ItemId
    JOIN Header h ON i.HeaderId = h.HeaderId
WHERE
    d.DetailId = @DetailId

然而,这是主观的,仅仅是我个人的偏好。

当您开始包含OUTER JOIN时,它变得不那么主观...尝试构建您的查询以避免任何RIGHT OUTER JOIN s,而是使用LEFT OUTER JOIN

默认情况下不要使用连接提示......实际上你几乎从不使用它们。查询优化器在选择最佳执行计划方面做得非常好。我只遇到过一个需要提供连接提示来改进计划的实例...它在当时运行查询的服务器上有很大帮助,但是当数据库迁移到不同的服务器时,我的加入提示销毁了查询的性能。因此,重申一下,提供联接提示通常是一个坏主意。

答案 1 :(得分:0)

顺序很大程度上是美学的,但我确实认为对表格的顺序和ON条件中的术语都有一个约定,以避免混淆。

查询提示仅适用于特殊情况,虽然您可能会发现需要使用它们的情况(通常会牺牲性能以减少并发性问题),但您应该总是尝试找到一种更强大的方法来解决问题。

[1] 我知道一个案例,其中订单很重要:

CREATE TABLE A (
  id int IDENTITY PRIMARY KEY,
  name varchar
);

CREATE TABLE B (
  id int IDENTITY PRIMARY KEY,
  a_id int FOREIGN KEY REFERENCES A (id),
  name varchar
);

SELECT *
FROM A
INNER LOOP JOIN B on A.id = B.a_id;

SELECT *
FROM B
INNER LOOP JOIN A on A.id = B.a_id;

第一个选择执行两次索引扫描,第二次执行扫描和搜索。这是避免提示的另一个好理由。