12

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

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

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

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

那是对的吗?

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

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

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

4

2 回答 2

12

编辑:根据您的问题(和 Kirk Woll 的)评论,您应该了解连接的顺序是美观的,并且不会直接影响生成的执行计划。查询优化器将以最有效的顺序执行连接,并在绝大多数时间使用适当的连接操作,无需任何提示。

当涉及到您的连接顺序的美学时,这有点主观,但我会说在阅读查询时以任何合乎逻辑的顺序将您的表连接在一起......如果您从@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。

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

于 2012-03-29T14:41:26.373 回答
0

该顺序主要是[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;

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

于 2012-06-01T13:44:02.963 回答