【问题标题】:SQL:Oracle - Cartesian product - in which caseSQL:Oracle - 笛卡尔积 - 在这种情况下
【发布时间】:2018-12-03 19:01:09
【问题描述】:

阅读 Karen Morten 的“Pro Oracle SQL”,第 9 页“FROM 子句”说

连接按以下顺序处理

  1. 交叉连接
  2. 内连接
  3. 外连接

那么无论是内连接还是外连接,Oracle 是否总是创建连接中涉及的两个表的笛卡尔积?

表 A 的值是 1 到 10(唯一),表 B 的值是 (2,4,6,8)

内连接:

select a.a1, b.b1 from a,b where a.a1 = b.b1;

外连接:

select a.a1, b.b1 from a,b where a.a1 = (+) b.b1;

根据

形成结果
  • 创建一个 10*4 的笛卡尔积,然后根据条件(外或等)显示记录
  • 不要创建笛卡尔积,只创建基于连接谓词的结果集(equi join 只是不确定这是否可以用于外连接,我认为笛卡尔积方法套件适用于外连接)

【问题讨论】:

  • 要求解释?
  • 我认为这句话可能是在谈论当多个不同类型的连接在同一语句中时会发生什么。不过,我不确定它是否正确。 See the documentation for an explanation of how joins are processed.
  • 我会说“连接按以下顺序处理:1,交叉连接2,内连接3,外连接”的说法是不正确的; Oracle 的优化器根据它认为最好的方式确定应该连接表的顺序。这可能是在最后、第一个或中间的某个地方处理笛卡尔/交叉连接。
  • 如果这本书解释了使用逗号语法的连接,那么再找一本书。您应该学习正确的 JOIN 语法——它更强大,并且几十年来一直是标准。
  • @GordonLinoff - 不,这不是作者使用的语法,是我觉得 JOIN 语法有困难。

标签: sql oracle join cartesian


【解决方案1】:

不,它不会为内部或外部联接构建两个表的笛卡尔积。

当一个或多个表对语句中的任何其他表没有任何连接条件时,数据库使用笛卡尔连接。" Database SQL Tuning Guide

因此,在您的示例中,仅当 where 子句为空时才进行笛卡尔连接:

EXPLAIN PLAN FOR
SELECT a.a1, b.b1 FROM a,b;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
-----------------------------------------------------------------------------
| Id  | Operation            | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |      |    40 |   240 |    10   (0)| 00:00:01 |
|   1 |  MERGE JOIN CARTESIAN|      |    40 |   240 |    10   (0)| 00:00:01 |
|   2 |   TABLE ACCESS FULL  | B    |     4 |    12 |     3   (0)| 00:00:01 |
|   3 |   BUFFER SORT        |      |    10 |    30 |     7   (0)| 00:00:01 |
|   4 |    TABLE ACCESS FULL | A    |    10 |    30 |     2   (0)| 00:00:01 |
-----------------------------------------------------------------------------

    SELECT a.a1, b.b1 FROM a,b;

它通常使用三种连接方法之一,在同一个document中进行了解释。

在您的情况下,它使用“哈希连接”进行内部连接:

EXPLAIN PLAN FOR
SELECT a.a1, b.b1 FROM a,b WHERE a.a1 = b.b1;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     4 |    24 |     6   (0)| 00:00:01 |
|*  1 |  HASH JOIN         |      |     4 |    24 |     6   (0)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| B    |     4 |    12 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| A    |    10 |    30 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("A"."A1"="B"."B1")

以及用于外部联接的“散列联接外部”:

EXPLAIN PLAN FOR
SELECT a.a1, b.b1 FROM a,b WHERE a.a1 = b.b1(+);
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |    10 |    60 |     6   (0)| 00:00:01 |
|*  1 |  HASH JOIN OUTER   |      |    10 |    60 |     6   (0)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| A    |    10 |    30 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| B    |     4 |    12 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("A"."A1"="B"."B1"(+))

【讨论】:

  • 好的,对于内连接和外连接,它不需要笛卡尔积。明白了。所以对于一个完整的外部连接,我认为它应该是创建一个笛卡尔积。原因,笛卡尔积可用于匹配左右外连接条件。我的问题是除了没有连接条件的情况外,在什么条件下使用笛卡尔积?
  • 完全外连接和笛卡尔连接之间存在技术差异。刚刚检查了两个表的连接,每个表有 300 万行:280 万行的连接时间为 6.2 秒,完全外连接:490 万行的连接时间为 7.4 秒。几分钟后交叉连接仍在运行。
  • 对于您的具体问题,请查看When the Optimizer Considers Cartesian Joins。基本上,它使用笛卡尔连接,1)如果你忘记了 where 子句,2)如果你强制它或 3)如果它更快,例如如果你将两个小表连接到一个大表,它可能会交叉连接两个小表.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-28
  • 2013-12-25
  • 2013-07-14
  • 2015-07-13
  • 2016-10-08
相关资源
最近更新 更多