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 JOIN
s 时,它变得不那么主观了...尝试构造您的查询以避免任何RIGHT OUTER JOIN
s,而是使用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 - 加入表的正确顺序是啥?的主要内容,如果未能解决你的问题,请参考以下文章