关于Oralce中的连接(外连接和内连接) oraclejoininnerouter
程序员文章站
2022-07-12 19:29:56
...
Note:2009-1-15
Oracle必须为每对行源执行连接操作,连接的方法包括嵌套循环、排序合并、散列连接、笛卡尔积等。
1.嵌套循环连接的成本计算公式:
cost = access cost of A + (access cost of B * number of rows from A)
2.散列连接的成本计算公式:
cost = (access cost of A * number of hash partitions of B) + access cost of B
3.排序合并连接的成本计算公式:
cost = access cost of A + access cost of B + (sort cost of A + sort cost of B)
********************
Note:2009-1-15
1.use_nl:use nesting loop
2.use_hash:use hash
3.use_merge use merge
*****************
Note:2009-1-15
SQL> show parameter workarea_size_policy
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
workarea_size_policy string AUTO
SQL> show parameter pga_aggregate_target
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
pga_aggregate_target big integer 629145600
*****************************
Note:2009-1-15
不论是嵌套循环外连接还是散列外连接,CBO不会根据成本去选择连接顺序,被驱动的表总是含有(+)的一方:
SQL> select /*+ordered use_nl(t1 t2)*/ t1.msisdn,t2.msisdn from t1,t2 where t1.msisdn(+)=t2.msisdn;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=100 Card=99 Bytes=2178)
1 0 NESTED LOOPS (OUTER) (Cost=100 Card=99 Bytes=2178)
2 1 INDEX (FULL SCAN) OF 'IND_T2' (NON-UNIQUE) (Cost=1 Card=99 Bytes=1089)
3 1 INDEX (RANGE SCAN) OF 'IND_T1' (NON-UNIQUE) (Cost=1 Card=1 Bytes=11)
虽然使用了ORDERED提示,试图以t1作为驱动表,可是由于是外连接,仍然是以t2作为驱动表。换成散列连接也是一样
SQL> select /*+ordered use_hash(t1 t2)*/ t1.msisdn,t2.msisdn from t1,t2 where t1.msisdn(+)=t2.msisdn;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=4 Card=99 Bytes=2178)
1 0 HASH JOIN (OUTER) (Cost=4 Card=99 Bytes=2178)
2 1 INDEX (FULL SCAN) OF 'IND_T2' (NON-UNIQUE) (Cost=1 Card=99 Bytes=1089)
3 1 INDEX (FAST FULL SCAN) OF 'IND_T1' (NON-UNIQUE) (Cost=2 Card=999 Bytes=10989)
******************************
Note:2009-1-15
select t1.msisdn,t2.msisdn
from t1
full outer join t2
on t1.msisdn=t2.msisdn
order by t2.msisdn
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=15 Card=1000 Bytes=36000)
1 0 SORT (ORDER BY) (Cost=15 Card=1000 Bytes=36000)
2 1 VIEW (Cost=6 Card=1000 Bytes=36000)
3 2 UNION-ALL
4 3 NESTED LOOPS (OUTER) (Cost=2 Card=999 Bytes=21978)
5 4 INDEX (FAST FULL SCAN) OF 'IND_T1' (NON-UNIQUE) (Cost=2 Card=999 Bytes=10989)
6 4 INDEX (RANGE SCAN) OF 'IND_T2' (NON-UNIQUE)
7 3 HASH JOIN (ANTI) (Cost=4 Card=1 Bytes=22)
8 7 INDEX (FULL SCAN) OF 'IND_T2' (NON-UNIQUE) (Cost=1 Card=99 Bytes=1089)
9 7 INDEX (FAST FULL SCAN) OF 'IND_T1' (NON-UNIQUE) (Cost=2 Card=999 Bytes=10989)
**********************************************************
说明:full outer join = left outer join + right outer join +union all
oracle中hint的用法: select /*+keyword_parameter*/ selected_column_set from table_name where query_condition
Note:2009-1-15
排序合并连接(Sort Merge Join, SMJ):
对于非等值连接,这种连接方式的效率是比较高的,因此主要用于不等价连接,如<、 <=、 >、 >=,但是不包括 <>,如果在关联的列上都有索引,效果更好。对于将两个较大的row source做连接,或者连接列缺乏可使用或可选择性的索引,该连接方法比NL连接要好一些。但是如果sort merge返回的row source过大,则又会导致使用过多的rowid在表中查询数据时,数据库性能下降,因为过多的I/O。所有的表都需要排序。它为最优化的吞吐量而设计,并且在结果没有全部找到前不返回数据。
嵌套循环(Nested Loops, NL):
如果driving row source(外部表)比较小,并且在inner row source(内部表)上 有唯一索引,或有高选择性非唯一索引时,使用这种方法可以得到较好的效率。
NESTED LOOPS有其它连接方法没有的的一个优点是:可以先返回已经 连接的行,而不必等待所有的连接操作理完才返回数据, 这可以实现快速的响应时间。
哈希连接(Hash Join, HJ):
一般来说,其效率应该好于其它2种连接,但是这种连接只能用在 CBO优化器中,而且需要设置合适的hash_area_size参数, 才能取得较好的性能。
在两个较大的row source之间连接时会取得相对较好的效率,在一个 row source较小时则能取得更好的效率。只能用于等值连接中
编写于【2009-01-15】
Oracle必须为每对行源执行连接操作,连接的方法包括嵌套循环、排序合并、散列连接、笛卡尔积等。
1.嵌套循环连接的成本计算公式:
cost = access cost of A + (access cost of B * number of rows from A)
2.散列连接的成本计算公式:
cost = (access cost of A * number of hash partitions of B) + access cost of B
3.排序合并连接的成本计算公式:
cost = access cost of A + access cost of B + (sort cost of A + sort cost of B)
********************
Note:2009-1-15
1.use_nl:use nesting loop
2.use_hash:use hash
3.use_merge use merge
*****************
Note:2009-1-15
SQL> show parameter workarea_size_policy
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
workarea_size_policy string AUTO
SQL> show parameter pga_aggregate_target
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
pga_aggregate_target big integer 629145600
*****************************
Note:2009-1-15
不论是嵌套循环外连接还是散列外连接,CBO不会根据成本去选择连接顺序,被驱动的表总是含有(+)的一方:
SQL> select /*+ordered use_nl(t1 t2)*/ t1.msisdn,t2.msisdn from t1,t2 where t1.msisdn(+)=t2.msisdn;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=100 Card=99 Bytes=2178)
1 0 NESTED LOOPS (OUTER) (Cost=100 Card=99 Bytes=2178)
2 1 INDEX (FULL SCAN) OF 'IND_T2' (NON-UNIQUE) (Cost=1 Card=99 Bytes=1089)
3 1 INDEX (RANGE SCAN) OF 'IND_T1' (NON-UNIQUE) (Cost=1 Card=1 Bytes=11)
虽然使用了ORDERED提示,试图以t1作为驱动表,可是由于是外连接,仍然是以t2作为驱动表。换成散列连接也是一样
SQL> select /*+ordered use_hash(t1 t2)*/ t1.msisdn,t2.msisdn from t1,t2 where t1.msisdn(+)=t2.msisdn;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=4 Card=99 Bytes=2178)
1 0 HASH JOIN (OUTER) (Cost=4 Card=99 Bytes=2178)
2 1 INDEX (FULL SCAN) OF 'IND_T2' (NON-UNIQUE) (Cost=1 Card=99 Bytes=1089)
3 1 INDEX (FAST FULL SCAN) OF 'IND_T1' (NON-UNIQUE) (Cost=2 Card=999 Bytes=10989)
******************************
Note:2009-1-15
select t1.msisdn,t2.msisdn
from t1
full outer join t2
on t1.msisdn=t2.msisdn
order by t2.msisdn
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=15 Card=1000 Bytes=36000)
1 0 SORT (ORDER BY) (Cost=15 Card=1000 Bytes=36000)
2 1 VIEW (Cost=6 Card=1000 Bytes=36000)
3 2 UNION-ALL
4 3 NESTED LOOPS (OUTER) (Cost=2 Card=999 Bytes=21978)
5 4 INDEX (FAST FULL SCAN) OF 'IND_T1' (NON-UNIQUE) (Cost=2 Card=999 Bytes=10989)
6 4 INDEX (RANGE SCAN) OF 'IND_T2' (NON-UNIQUE)
7 3 HASH JOIN (ANTI) (Cost=4 Card=1 Bytes=22)
8 7 INDEX (FULL SCAN) OF 'IND_T2' (NON-UNIQUE) (Cost=1 Card=99 Bytes=1089)
9 7 INDEX (FAST FULL SCAN) OF 'IND_T1' (NON-UNIQUE) (Cost=2 Card=999 Bytes=10989)
**********************************************************
说明:full outer join = left outer join + right outer join +union all
oracle中hint的用法: select /*+keyword_parameter*/ selected_column_set from table_name where query_condition
Note:2009-1-15
排序合并连接(Sort Merge Join, SMJ):
对于非等值连接,这种连接方式的效率是比较高的,因此主要用于不等价连接,如<、 <=、 >、 >=,但是不包括 <>,如果在关联的列上都有索引,效果更好。对于将两个较大的row source做连接,或者连接列缺乏可使用或可选择性的索引,该连接方法比NL连接要好一些。但是如果sort merge返回的row source过大,则又会导致使用过多的rowid在表中查询数据时,数据库性能下降,因为过多的I/O。所有的表都需要排序。它为最优化的吞吐量而设计,并且在结果没有全部找到前不返回数据。
嵌套循环(Nested Loops, NL):
如果driving row source(外部表)比较小,并且在inner row source(内部表)上 有唯一索引,或有高选择性非唯一索引时,使用这种方法可以得到较好的效率。
NESTED LOOPS有其它连接方法没有的的一个优点是:可以先返回已经 连接的行,而不必等待所有的连接操作理完才返回数据, 这可以实现快速的响应时间。
哈希连接(Hash Join, HJ):
一般来说,其效率应该好于其它2种连接,但是这种连接只能用在 CBO优化器中,而且需要设置合适的hash_area_size参数, 才能取得较好的性能。
在两个较大的row source之间连接时会取得相对较好的效率,在一个 row source较小时则能取得更好的效率。只能用于等值连接中
编写于【2009-01-15】
上一篇: SQL Joins图解