连接因式分解(Join Factorization)是优化器处理带union all的目标SQL的一种优化手段,它是指优化器在处理以union all连接的目标SQL的各个分支时,不再原封不动地分别重复执行每个分支,而是会把各个分支中公共的部分提出来作为一个单独的结果集,然后再和原union all中剩下的部分做表连接。连接因式分解在Oracle 11gr2中才被引入,它的好处是显而易见的。如果不把union all中公共的部分提出来,则意味着这些公共部分中所包含的表会在union all的各个分支中被重复访问;而连接因式分解则能够在最大程度上避免这种重复访问现象的产生,当union all的公共部分所包含的表的数据量很大时,减少一次对大表的重复访问,那也意味着执行效率的巨大提升。
我们来看一个连接因式分解的实例。先来看用union all连接的例子:
select t2.prod_id as prod_id
from sales t2,customers t3
where t2.cust_id=t3.cust_id
and t3.cust_gender='MALE'
union all
select t2.prod_id as prod_id
from sales t2,customers t3
where t2.cust_id=t3.cust_id
and t3.cust_gender='FEMALE';
范例SQL的union all的各个分支中仅仅是针对表customers的列cust_gender的限制条件不一样,剩下的部分都是一模一样的,这也意味着表sales就是范例SQL的公共部分。如果这里Oracle不把sales表提出来,不对此SQL做连接因式分解,那就意味着要重复访问表sales两次。
来验证一下。先在Oracle 10gr2中执行范例SQL:
SQL> select t2.prod_id as prod_id
2 from sales t2,customers t3
3 where t2.cust_id=t3.cust_id
4 and t3.cust_gender='MALE'
5 union all
6 select t2.prod_id as prod_id
7 from sales t2,customers t3
8 where t2.cust_id=t3.cust_id
9 and t3.cust_gender='FEMALE';
no rows selected
Execution Plan
----------------------------------------------------------
Plan hash value: 4184572088
------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1837K| 28M| 1098 (54)| 00:00:14 | | |
| 1 | UNION-ALL | | | | | | | |
|* 2 | HASH JOIN | | 918K| 14M| 549 (8)| 00:00:07 | | |
|* 3 | VIEW | index$_join$_002 | 27236 | 186K| 122 (4)| 00:00:02 | | |
|* 4 | HASH JOIN | | | | | | | |
| 5 | BITMAP CONVERSION TO ROWIDS| | 27236 | 186K| 2 (0)| 00:00:01 | | |
|* 6 | BITMAP INDEX SINGLE VALUE | CUSTOMERS_GENDER_BIX | | | | | | |
| 7 | INDEX FAST FULL SCAN | CUSTOMERS_PK | 27236 | 186K| 147 (2)| 00:00:02 | | |
| 8 | PARTITION RANGE ALL | | 918K| 8075K| 413 (6)| 00:00:05 | 1 | 28 |
| 9 | TABLE ACCESS FULL | SALES | 918K| 8075K| 413 (6)| 00:00:05 | 1 | 28 |
|* 10 | HASH JOIN | | 918K| 14M| 549 (8)| 00:00:07 | | |
|* 11 | VIEW | index$_join$_004 | 27750 | 189K| 122 (4)| 00:00:02 | | |
|* 12 | HASH JOIN | | | | | | | |
| 13 | BITMAP CONVERSION TO ROWIDS| | 27750 | 189K| 2 (0)| 00:00:01 | | |
|* 14 | BITMAP INDEX SINGLE VALUE | CUSTOMERS_GENDER_BIX | | | | | | |
| 15 | INDEX FAST FULL SCAN | CUSTOMERS_PK | 27750 | 189K| 147 (2)| 00:00:02 | | |
| 16 | PARTITION RANGE ALL | | 918K| 8075K| 413 (6)| 00:00:05 | 1 | 28 |
| 17 | TABLE ACCESS FULL | SALES | 918K| 8075K| 413 (6)| 00:00:05 | 1 | 28 |
------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------