TSQL - 加入表的正确顺序是啥?

Posted

技术标签:

【中文标题】TSQL - 加入表的正确顺序是啥?【英文标题】:TSQL - What is the proper order to joining tables?TSQL - 加入表的正确顺序是什么? 【发布时间】:2012-04-13 05:28:58 【问题描述】:

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

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

在一个查询中,我将 header/item/details 连接在一起,并为这些记录查找各种信息。

加入时,我会尽量按照它们的相关性来排列。例如:我的标题有两个查找表,所以我会在加入我的项目表之前加入这些查找表。

正确吗?

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

我应该在加入小表时使用 loop 提示,而在加入 openrowsets 时应该使用 merge 提示吗?

我确信答案是“视情况而定”,但一些有效加入的一般准则会非常有帮助。谢谢!

【问题讨论】:

在大多数情况下,您不需要指定连接类型(合并/循环/哈希)。如果您这样做,则可能应该解决潜在的问题,而不是加入提示创可贴。 除非您非常清楚自己在做什么,并且您了解查询执行计划,否则切勿使用查询提示。 【参考方案1】:

编辑:根据您的问题(和 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 JOINs 时,它变得不那么主观了...尝试构造您的查询以避免任何RIGHT OUTER JOINs,而是使用LEFT OUTER JOIN's。

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

【讨论】:

也许 OP 不知道加入顺序与执行计划无关,纯粹是审美? @KirkWoll 这是我忽略的一个很好的观点......我会在我的回答中澄清这一点。 @Kirk,这正是我要问的原因。顺序完全不相关? @IronicMuffin - 阅读OPTION (FORCE ORDER) - 这是你必须特别要求的。 顺序会影响执行计划,至少在使用提示的情况下是这样。【参考方案2】:

顺序主要是 [1] 美观,但我确实认为对表格的顺序和 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;

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

【讨论】:

以上是关于TSQL - 加入表的正确顺序是啥?的主要内容,如果未能解决你的问题,请参考以下文章

查询中的 TSQL 顺序/序列组

TSQL——on 子句的顺序是不是重要

TSQL Join、查询处理顺序和存储

在 Opengl 中使用矩阵的正确顺序是啥?

在先通道和最后通道之间更改图像通道顺序的正确方法是啥?

AddCors 到 .Net Core 的正确顺序是啥?