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

SQL:Oracle - Cartesian product - in which case

阅读 Karen Morten 的 "Pro Oracle SQL",第 9 页 "FROM clause" 说

Joins are processed in the following order

  1. Cross Join
  2. Inner join
  3. Outer join

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

Table A 的值为 1 到 10(唯一),table 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;

根据

形成结果

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

The database uses a Cartesian join when one or more of the tables does not have any join conditions to any other tables in the statement." 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 中有解释。

在您的例子中,它使用 "hash join" 作为内部联接:

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")

和一个 "hash join outer" 用于外部连接:

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"(+))