ORACLE表连接

ORACLE表连接



一、什么是表连接?
表的连接是指在一个SQL语句中通过表与表之间的关联,从一个或多个表检索出相关的数据。


二、ORACLE的优化器使用的表连接有哪些?
1.嵌套循环连接(NESTED LOOP JOIN)
2.群集连接(CLUSTER JOIN)
3.排序合并连接(SORT MERGE JOIN)
4.笛卡尔连接(CARTESIAL JOIN)
5.哈希连接(HASH JOIN)
6.索引连接(INDEX JOIN)


三、各种表连接的内部处理流程
1.嵌套循环连接(NESTED LOOP JOIN)
1)ORACLE优化器根据基于规则RBO或基于成本CBO的原则,选择两个表中的一个作为驱动表,并指定其为外部表;
2)ORACLE优化器再将另外一个表指定为内部表;
3)ORACLE从外部表中读取第一行,然后和内部表中的数据逐一进行对比,所有匹配的记录放在结果集中;
4)ORACLE读取外部表中的第二行,再和内部表中的数据逐一进行对比,所有匹配的记录添加到结果集中;
5)重复上述步骤,直到外部表中的所有记录全部处理完;
6)最后产生满足要求的结果集。

2.群集连接(CLUSTER JOIN)
群集连接实际上是嵌套循环连接的一种特例。
1)ORACLE优化器根据基于规则RBO或基于成本CBO的原则,选择两个表中的一个作为驱动表,并指定其为外部表;
2)ORACLE优化器再将另外一个表指定为内部表;
3)ORACLE从外部表中读取第一行,然后在内部表中使用CLUSTER索引查找能够匹配到的纪录,所有匹配的记录放在结果集中;
4)ORACLE读取外部表中的第二行,再在内部表中使用CLUSTER索引查找能够匹配到的纪录,所有匹配的记录添加到结果集中;
5)重复上述步骤,直到外部表中的所有记录全部处理完;
6)最后产生满足要求的结果集。
注:群集连接的效率极高,因为两个参加连接的行源表实际上处于同一个物理块上。但是,群集连接也有其限制,没有群集的两个表不可能用群集连接。

3.排序合并连接(SORT MERGE JOIN)
1) 优化器判断第一个行源表是否已经排序,如果已经排序,则到第3步,否则到第2步;
2) 第一个源表排序;
3) 优化器判断第二个行源表是否已经排序,如果已经排序,则到第5步,否则到第4步;
4) 第二个源表排序;
5) 已经排过序的两个源表进行合并操作,并生成最终的结果集。
注:在缺乏数据的选择性或者可用的索引时,或者两个行源表都过于庞大(所选的数据超过表记录数的5%)时,排序合并连接将比嵌套循环连更加高效。排列合并连接需要比较大的临时内存块,以用于排序,

这将导致在临时表空间占用更多的内存和磁盘I/O。

4.笛卡尔连接(CARTESIAL JOIN)
笛卡尔连接是指在sql语句中没有写出表连接的条件,优化器把第一个表的每一条记录和第二个表的所有纪录相连接。如果第一个表的纪录数为m, 第二个表的纪录数为m,则会产生m*n条纪录数。

5.哈希连接(HASH JOIN)
当内存能够提供足够的空间时,哈希(HASH)连接是ORACLE优化器通常的选择。哈希连接中,优化器根据统计信息,首先选择两个表中的小表,在内存中建立这张表的基于连接键的哈希表;优化器再扫描表

连接中的大表,将大表中的数据与哈希表进行比较,如果有相关联的数据,则将数据添加到结果集中。当表连接中的小表能够完全cache到可用内存的时候,哈希连接的效果最佳。哈希连接的成本只是两

个表从硬盘读入到内存的成本。但是,如果哈希表过大而不能全部cache到可用内存时,优化器将会把哈希表分成多个分区,再将分区逐一cache到内存中。当表的分区超过了可用内存时,分区的部分数

据就会临时地写到磁盘上的临时表空间上。因此,分区的数据写磁盘时,比较大的区间(EXTENT)会提高I/O性能。ORACLE推荐的临时表空间的区间是1MB。临时表空间的区间大小由UNIFORM SIZE指定。

当哈希表构建完成后,进行下面的处理:
1)第二个大表进行扫描
2)如果大表不能完全cache到可用内存的时候,大表同样会分成很多分区
3)大表的第一个分区cache到内存
4)对大表第一个分区的数据进行扫描,并与哈希表进行比较,如果有匹配的纪录,添加到结果集里面
5)与第一个分区一样,其它的分区也类似处理。
6)所有的分区处理完后,ORACLE对产生的结果集进行归并,汇总,产生最终的结果。
注:当哈希表过大或可用内存有限,哈希表不能完全CACHE到内存。随着满足连接条件的结果集的增加,可用内存会随之下降,这时已经CACHE到内存的数据可能会重新写回到硬盘去。如果出现这种情况

,系统的性能就会下降。当连接的两个表是用等值连接并且表的数据量比较大时,优化器才可能采用哈希连接。哈希连接是基于CBO的。只有在数据库初始化参数HASH_JOIN_ENABLED设为True,并且为参数

PGA_AGGREGATE_TARGET设置了一个足够大的值的时候,ORACLE才会使用哈希边连接。

6.索引连接(INDEX JOIN)
如果一组已存在的索引包含查询条件所需要的信息,那么优化器可能会选择索引连接,通过索引查找结果集。


四、几种常见表连接的比较
类别
嵌套循环连接 排序合并连接 哈希连接
HINT USE_NL USE_MERGE USE_HASH
条件 任何连接 不等价连接 等价连接
资源 CPU、磁盘I/O 内存、临时表空间 内存、临时表空间
特点 当有高选择性索引或进行限制性搜索时效率较高,能够快速返回第一次的搜索结果。 当缺乏索引或者索引条件模糊时,排序合并连接比嵌套循环有效 当缺乏索引或者索引条件模式时,哈希连接比嵌套循环有效。通常比排序合并连接快。
缺点 当索引丢失或者查询条件限制不够时,效率很低;当表的记录数多时,效率低 所有的表都需要排序。它为最优化的吞吐量而设计,并且在结果没有全部找到前不返回数据。 为建立哈希表,需要大量内存。第一次的结果返回较慢


五、连接应用举例
SQL> create table user_info(user_id char(32),user_name varchar2(10));
SQL> create table dev_info(dev_no char(32),user_id char(32),dev_type varchar2(10));
SQL> set autotrace traceonly explain;
1.嵌套循环连接(NESTED LOOP JOIN)
SQL> select /*+ use_nl(a b) */ a.user_name, b.dev_no
from user_info a, dev_info b
where a.user_id = b.user_id;

Execution Plan
----------------------------------------------------------
Plan hash value: 1772694585

--------------------------------------------------------------------------------
| Id  | Operation       | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |           |     1 |    48 |     4     (0)| 00:00:01 |
|   1 |  NESTED LOOPS       |           |     1 |    48 |     4     (0)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| USER_INFO |     1 |    24 |     2     (0)| 00:00:01 |
|*  3 |   TABLE ACCESS FULL| DEV_INFO  |     1 |    24 |     2     (0)| 00:00:01 |
--------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("A"."USER_ID"="B"."USER_ID")
2.排序合并连接(SORT MERGE JOIN)
SQL> select /*+ use_merge(a b) */ a.user_name, b.dev_no
from user_info a, dev_info b
where a.user_id > b.user_id;  2    3  

Execution Plan
----------------------------------------------------------
Plan hash value: 261599494

--------------------------------------------------------------------------------
-

| Id  | Operation        | Name    | Rows    | Bytes | Cost (%CPU)| Time
|

--------------------------------------------------------------------------------
-

|   0 | SELECT STATEMENT    |        |     1 |    48 |     6  (34)| 00:00:01
|

|   1 |  MERGE JOIN        |        |     1 |    48 |     6  (34)| 00:00:01
|

|   2 |   SORT JOIN        |        |     1 |    24 |     3  (34)| 00:00:01
|

|   3 |    TABLE ACCESS FULL| USER_INFO |     1 |    24 |     2   (0)| 00:00:01
|

|*  4 |   SORT JOIN        |        |     1 |    24 |     3  (34)| 00:00:01
|

|   5 |    TABLE ACCESS FULL| DEV_INFO    |     1 |    24 |     2   (0)| 00:00:01
|

--------------------------------------------------------------------------------
-


Predicate Information (identified by operation id):
---------------------------------------------------

   4 - access(INTERNAL_FUNCTION("A"."USER_ID")>INTERNAL_FUNCTION("B"."USE
          R_ID"))
       filter(INTERNAL_FUNCTION("A"."USER_ID")>INTERNAL_FUNCTION("B"."USE
          R_ID"))

3.哈希连接(HASH JOIN)
SQL> select a.user_name, b.dev_no
from user_info a, dev_info b
where a.user_id = b.user_id;

Execution Plan
----------------------------------------------------------
Plan hash value: 1657342960

--------------------------------------------------------------------------------
| Id  | Operation       | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |           |     1 |    48 |     5    (20)| 00:00:01 |
|*  1 |  HASH JOIN       |           |     1 |    48 |     5    (20)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| USER_INFO |     1 |    24 |     2     (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| DEV_INFO  |     1 |    24 |     2     (0)| 00:00:01 |
--------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("A"."USER_ID"="B"."USER_ID")

你可能感兴趣的:(ORACLE表连接)