我的google-fu和so-fu在这里让我失望,所以我不妨问。
我有很多查询,其中有多个连接。
在一个查询中,我将标题/项目/详细信息一起加入,以及查找这些记录的各种信息。
加入时,我会尽量保持相关的顺序。例如:我的标题有两个查找表,所以在加入我的项目表之前我会加入那些。
这是对的吗?
在查找表之前加入更大的表是否更好?或相反亦然?
我是否应该在加入小型表时使用loop
提示,并在加入openrowsets时使用merge
提示?
我确信答案是“它取决于”,但有效和高效地加入的一些一般指导方针将非常有帮助。谢谢!
答案 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;
第一个选择执行两次索引扫描,第二次执行扫描和搜索。这是避免提示的另一个好理由。