hash join不一定会排序,或者说大多数情况下都不需要排序
hash join的驱动表所对应的连接列的可选择性尽可能好,因为这个选择性会影响对应Hash Bucket中的记录数,而Hash Bucket中的记录数又会直接影响从该Hash Bucket中查找匹配记录的效率。如果一个Hash Bucket里所包含的记录数过多,则可能会严重降低所对应哈希连接的执行效率,此时典型的表现就是该哈希连接执行了很长时间都没有结束,数据库所在数据库服务器上的CPU占用率很高,但目标SQL消耗的逻辑读却很低,因为此时大部分时间都消耗在了遍历上述Hash Bucket里的所有记录上,而遍历Hash Bucket里的记录这个动作发生在PGA的工作区里,所以不耗费逻辑读。
哈希连接只适用于CBO,它也只能用于等值连接条件
哈希连接适合于小表和大表之间做表连接且连接结果集的记录数较多的情形,特别是在小表的连接列的可选择性非常好的情况下,这时哈希连接的执行时间就可以近似看做是和全表扫描那个大表所耗费的时间相当。
我们可以借助10104事件所产生的trace来观察目标sql在做hash时的大致过程和一些统计信息(比如使用了多少Hash Partition、多少个Hash Bucket以及各个Hash Bucket都分别有多少条记录等),10104事件在实际诊断hash join的性能问题时非常有用。
过程如下:
oradebug setmypid
oradebug event 10104 trace name context forever,level 1
set autotrace traceonly
执行目标sql(必须实际执行sql)
oradebug tracefile_name
一个10104事件所产生的trace内容如下
### Hash table overall statistics ###
Total buckets: 131072 Empty buckets: 131048 Non-empty buckets: 24
Total number of rows: 75160
Maximum number of rows in a bucket: 37789
Average number of rows in non-empty buckets: 3131.666748