当一个或多个表对语句中的任何其他表没有任何连接条件时,数据库将使用笛卡尔连接。
优化器将一个数据源的每一行与另一数据源的每一行连接在一起,从而创建两组数据集的笛卡尔积。因此,使用以下公式计算联接产生的总行数,其中,rs1是第一行集中rs2的行数和第二行集中的行数:
rs1 X rs2 = total rows in result set
- 当优化器考虑笛卡尔联接时 : 优化器仅在特定情况下才将笛卡尔联接用于两个行源。
- 笛卡尔联接如何工作笛卡尔联接 : 使用嵌套
FOR循环。 - 笛卡儿连接控制 : 的
ORDERED提示指示优化加入在它们出现的顺序表FROM条款。通过强制没有直接连接的两个行源之间的联接,优化器必须执行笛卡尔联接。
9.3.5.1当优化器考虑笛卡尔联接时
仅在特定情况下,优化器才将笛卡尔联接用于两个行源。
通常,情况是以下情况之一:
- 不存在加入条件 : 在某些情况下,优化器可能会选择两个表之间的公共过滤条件作为可能的连接条件。
注意: 如果笛卡尔联接出现在查询计划中,则可能是由于无意中省略了联接条件引起的。通常,如果查询联接了n个表,则需要n -1个联接条件才能避免笛卡尔联接。
- 笛卡尔联接是一种有效的方法。
例如,优化器可能会决定生成两个非常小的表的笛卡尔积,它们都连接到同一个大表。
- 该
ORDERED提示指定一个表之前,其加入指定表。
9.3.5.2笛卡尔联接如何工作
笛卡尔联接使用嵌套FOR循环。
在较高级别上,笛卡尔联接的算法如下所示,其中ds1通常是较小的数据集,而ds2较大的数据集是:
FOR ds1_row IN ds1 LOOP
FOR ds2_row IN ds2 LOOP
output ds1_row and ds2_row
END LOOP
END LOOP示例9-18笛卡尔联接
在此示例中,用户打算对employees和departments表执行内部联接,但意外地放弃了联接条件:
SELECT e.last_name, d.department_name
FROM employees e, departments d
执行计划如下:
--------------------------------------------------------------------------------
| Id| Operation | Name | Rows | Bytes |Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | |11 (100)| |
| 1 | MERGE JOIN CARTESIAN | | 2889 | 57780 |11 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL | DEPARTMENTS | 27 | 324 | 2 (0)| 00:00:01 |
| 3 | BUFFER SORT | | 107 | 856 | 9 (0)| 00:00:01 |
| 4 | INDEX FAST FULL SCAN| EMP_NAME_IX | 107 | 856 | 0 (0)| |
--------------------------------------------------------------------------------
在上述计划的步骤1中,CARTESIAN关键字指示存在笛卡尔连接。行数(2889)是27和107的乘积。
在步骤3中,该BUFFER SORT操作指示数据库正在将通过扫描emp_name_ix从SGA 获得的数据块复制到PGA。此策略避免了对数据库缓冲区高速缓存中相同块的多次扫描,这将生成许多逻辑读取并允许资源争用。
9.3.5.3笛卡尔联接控件
该ORDERED提示指示优化器按照表在FROM子句中出现的顺序连接表。通过强制没有直接连接的两个行源之间的联接,优化器必须执行笛卡尔联接。
示例9-19 ORDERED提示
在以下示例中,ORDERED提示指示优化器加入employees和locations,但没有加入条件连接这两个行源:
SELECT /*+ORDERED*/ e.last_name, d.department_name, l.country_id, l.state_province
FROM employees e, locations l, departments d
WHERE e.department_id = d.department_id
AND d.location_id = l.location_id
以下执行计划显示了locations(步骤6)和employees(步骤4)之间的笛卡尔乘积(步骤3 ),然后将其连接到departments表(步骤2):
--------------------------------------------------------------------------------
| Id| Operation | Name | Rows | Bytes |Cost (%CPU)|Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 37 (100)| |
|*1 | HASH JOIN | | 106 | 4664 | 37 (6)| 00:00:01 |
| 2 | TABLE ACCESS FULL | DEPARTMENTS | 27 | 513 | 2 (0)| 00:00:01 |
| 3 | MERGE JOIN CARTESIAN| | 2461 | 61525 | 34 (3)| 00:00:01 |
| 4 | TABLE ACCESS FULL | EMPLOYEES | 107 | 1177 | 2 (0)| 00:00:01 |
| 5 | BUFFER SORT | | 23 | 322 | 32 (4)| 00:00:01 |
| 6 | TABLE ACCESS FULL | LOCATIONS | 23 | 322 | 0 (0)| |
--------------------------------------------------------------------------------



