Oracle Table连接方式分析(3)

  当内存能够提供足够的空间时,哈希(HASH)连接是Oracle优化器通常的选择。哈希连接中,优化器根据统计信息,首先选择两个表中的小表,在内存中建立这张表的基于连接键的哈希表;优化器再扫描表连接中的大表,将大表中的数据与哈希表进行比较,如果有相关联的数据,则将数据添加到结果集中。

  当表连接中的小表能够完全cache到可用内存的时候,哈希连接的效果最佳。哈希连接的成本只是两个表从硬盘读入到内存的成本。

  但是,如果哈希表过大而不能全部cache到可用内存时,优化器将会把哈希表分成多个分区,再将分区逐一cache到内存中。当表的分区超过了可用内存时,分区的部分数据就会临时地写到磁盘上的临时表空间上。因此,分区的数据写磁盘时,比较大的区间(EXTENT)会提高I/O性能。ORACLE推荐的临时表空间的区间是1MB。临时表空间的区间大小由UNIFORMSIZE指定。

  当哈希表构建完成后,进行下面的处理:

  1)第二个大表进行扫描

  2)如果大表不能完全cache到可用内存的时候,大表同样会分成很多分区

  3)大表的第一个分区cache到内存

  4)对大表第一个分区的数据进行扫描,并与哈希表进行比较,如果有匹配的纪录,添加到结果集里面5)与第一个分区一样,其它的分区也类似处理。

  6)所有的分区处理完后,ORACLE对产生的结果集进行归并,汇总,产生最终的结果。

  当哈希表过大或可用内存有限,哈希表不能完全CACHE到内存。随着满足连接条件的结果集的增加,可用内存会随之下降,这时已经CACHE到内存的数据可能会重新写回到硬盘去。如果出现这种情况,系统的性能就会下降。

  当连接的两个表是用等值连接并且表的数据量比较大时,优化器才可能采用哈希连接。哈希连接是基于CBO的。只有在数据库初始化参数HASH_JOIN_ENABLED设为True,并且为参数PGA_AGGREGATE_TARGET设置了一个足够大的值的时候,Oracle才会使用哈希连接。HASH_AREA_SIZE是向下兼容的参数,但在Oracle9i之前的版本中应当使用HASH_AREA_SIZE。当使用ORDERED提示时,FROM子句中的第一张表将用于建立哈希表。

  可以通过在SQL语句中添加HINTS,强制ORACLE优化器产生哈希连接的执行计划。

  select/*+use_hash(ab)*/a.user_name,b.dev_nofromuser_infoa,dev_infobwherea.user_id=b.user_id;

  当缺少有用的索引时,哈希连接比嵌套循环连接更加有效。哈希连接也可能比嵌套循环连接更快,因为处理内存中的哈希表比检索B_树索引更加迅速。

案例:

11:59:56 SCOTT@ prod> select /*+ use_hash(d e)*/ e.ename,e.sal,d.deptno,d.dname

12:00:34  2    from dept d,emp e

12:00:34  3    where d.deptno=e.deptno ;

14 rows selected.

Elapsed: 00:00:00.05

Execution Plan

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

Plan hash value: 615168685

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

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

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

|  0 | SELECT STATEMENT  |      |    14 |  294 |    7  (15)| 00:00:01 |

|*  1 |  HASH JOIN        |      |    14 |  294 |    7  (15)| 00:00:01 |

|  2 |  TABLE ACCESS FULL| DEPT |    4 |    44 |    3  (0)| 00:00:01 |

|  3 |  TABLE ACCESS FULL| EMP  |    14 |  140 |    3  (0)| 00:00:01 |

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

Predicate Information (identified by operation id):

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

1 - access("D"."DEPTNO"="E"."DEPTNO")

Statistics

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

1  recursive calls

0  db block gets

15  consistent gets

0  physical reads

0  redo size

1107  bytes sent via SQL*Net to client

523  bytes received via SQL*Net from client

2  SQL*Net roundtrips to/from client

0  sorts (memory)

0  sorts (disk)

14  rows processed

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/9a66f03d876beb221ed69a297712672f.html