SQL:Oracle - 笛卡尔积 - 在这种情况下
SQL:Oracle - Cartesian product - in which case
阅读 Karen Morten 的 "Pro Oracle SQL",第 9 页 "FROM clause" 说
Joins are processed in the following order
- Cross Join
- Inner join
- 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;
根据
形成结果
- 创建 10*4 的笛卡尔积,然后根据条件(outer 或 equi)显示记录
- 不创建笛卡尔积,只创建基于连接谓词的结果集(equi join只是不确定是否可以用于外部连接,我认为笛卡尔积方法套件适用于外部连接)
不,它不会为内连接或外连接构建两个表的笛卡尔积。
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"(+))
阅读 Karen Morten 的 "Pro Oracle SQL",第 9 页 "FROM clause" 说
Joins are processed in the following order
- Cross Join
- Inner join
- 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;
根据
形成结果- 创建 10*4 的笛卡尔积,然后根据条件(outer 或 equi)显示记录
- 不创建笛卡尔积,只创建基于连接谓词的结果集(equi join只是不确定是否可以用于外部连接,我认为笛卡尔积方法套件适用于外部连接)
不,它不会为内连接或外连接构建两个表的笛卡尔积。
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"(+))