SQL:Oracle-笛卡尔积-在这种情况下

时间:2018-06-25 08:46:53

标签: sql oracle join cartesian

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

  

按以下顺序处理联接

     
      
  1. 交叉加入
  2.   
  3. 内部加入
  4.   
  5. 外部加入
  6.   

那么,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不能确定是否可以对外部联接进行此操作,我认为笛卡尔积方法套件适用于外部联接)

1 个答案:

答案 0 :(得分: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"(+))