【问题标题】:Order of tables in join query连接查询中的表顺序
【发布时间】:2011-04-27 23:26:47
【问题描述】:

我在 Oracle 文档中找到了这一段

如果你想选择每个人的名字 部门及其名称 经理,您可以将查询写入 两种方式之一。在第一个例子中 接下来是提示 /++ordered++/ 说按顺序加入 表出现在 FROM 子句中 尝试优化连接顺序。

SELECT /*+ordered*/ d.NAME, e.NAME
FROM DEPT d, EMP e WHERE d.MGR = e.SS#

或:

SELECT /*+ordered*/ d.NAME, e.NAME 
FROM EMP e, DEPT d WHERE d.MGR = e.SS# 

假设有 10 个部门 和 1000 名员工,以及内部 每个查询中的表都有一个索引 连接列。在第一个查询中, 第一个表产生 10 排位赛 行(在这种情况下,整个表)。 在第二个查询中,第一个表 产生 1000 个符合条件的行。这 第一个查询将访问 EMP 表 10 次并扫描 DEPT 表一次。 第二个查询将扫描 EMP 表一次,但将访问 DEPT 表 1000 次。因此第一个 查询将执行得更好。作为一个 经验法则,表格应该是 从最小有效排列 行数到最大有效 行数。有效行大小 查询中的表由以下方式获得 应用逻辑条件 完全在该表上解决。

但我没有正确理解这一点。如果表t1有m行,表t2有n行,sql引擎不会在这两种情况下都经过m x n行吗?

更新:感谢所有回复。我不会重写优化器,只是想确认一下我的想法。

【问题讨论】:

  • 您能否发布一个指向您阅读此文件的文档的链接?
  • 您在 Oracle 文档中的第二个查询中缺少 WHERE-clause。
  • @Peter - 添加 where 子句 :)

标签: sql oracle join


【解决方案1】:

嗯,第一种情况逻辑读取次数是 10+10,第二种情况是 1000+1000,每个部门平均读取 100 次。

但是,像这样使用 ORDERED hitn 编写查询并不是正常的做法。大多数情况下,最好将优化留给优化者。

我不确定您从哪个文档中获得了该引用,但在我看到的地方,它前面是您省略的这个非常重要的段落。我在这里引用它是为了其他可能认为这种编写查询的方法是标准的人的利益:

通常优化器会选择最好的 执行计划,最优顺序 要连接的表。万一 优化器没有产生好的效果 你可以控制的执行计划 使用提示的执行顺序 功能 SQL。有关更多信息,请参阅 Oracle 数据库精简版 SQL 参考。

-- Oracle® Database Lite Developer's Guide

【讨论】:

  • +1,虽然我认为它假设一个嵌套循环连接(如果没有过滤条件,可能会选择一个哈希连接)。文档假定嵌套循环连接(规则优化器?)并提倡使用提示的事实使我认为这个建议来自一个非常古老的文档(Oracle 7?)。无论如何,让优化器完成工作的好建议。
【解决方案2】:

这取决于 WHERE 语句。

SELECT /++ordered++/ d.NAME, e.NAME FROM DEPT d, EMP e WHERE d.MGR = e.SS#

将为每个部门选择所有经理。由于有 10 个部门,因此会提取 10 条记录。

SELECT /++ordered++/ d.NAME, e.NAME FROM EMP e, DEPT d

这将选择所有员工及其所在部门的名称。由于有 1000 名员工,您的结果集将有 1000 行。

JOIN 永远不会导致您的引擎循环遍历 m x n 行,如果 m < n,您的内部连接结果集将始终为 m

【讨论】:

  • 我不明白您所说的“如果 m
  • 即使连接键上没有索引也是如此吗? (同样,这只是为了知识。我知道不建议在非索引上加入。)
  • @Tony,这取决于您的 WHERE/ON 子句。在第一种情况下,结果集将包含 10 行,在第二个 1000 中。@Jerry 连接键上的索引是什么意思?
  • @Tony - 因为这是内部连接,不是 10,而不是 100?
  • @Anzeo - 我的意思是如果 e.SS# 和 d.MGR 上有索引。如果两列都没有索引,引擎不会对每条记录进行全面扫描吗?
【解决方案3】:

您真的在 oracle 文档中发现了这一点?

你不应该使用 ORDERED 提示,让 oracle 为你做决定——现在大部分时间都很好。

但是,连接顺序在性能方面会有所不同。

这个例子似乎在讨论 NESTED LOOPS 连接:

Case 1:
 -> 1 lookup to find 10 rows in table A
 -> 10 index lookups in table B

Case 2:
 -> 1 lookup to find 1000 rows in table B 
 -> 1000 index lookups in table A

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-26
    • 1970-01-01
    • 2011-11-12
    • 2015-11-25
    • 2018-03-06
    相关资源
    最近更新 更多