HASH (UNIQUE) in Oracle10g
Oracle10g在distinct操作时作了算法改进,使用Hash Unique 代理了以前的Sort Unique.该行为由隐藏参数”_gby_hash_aggregation_enabled”决定,optimizer_features_enable设置为10.2.0.1时默认为TRUE.
HASH UNIQUE 的CPU COST应该比SORT UNIQUE要低,同理常用HASH JOIN而少用SORT MERGE JOIN。
SQL> create table t as select * from dba_users;
Table created.
SQL> set autotrace on
SQL> select distinct password from t;
———————————–
| Id | Operation | Name |
———————————–
| 0 | SELECT STATEMENT | |
| 1 | SORT UNIQUE | |
| 2 | TABLE ACCESS FULL| T |
———————————–
Note
—–
- rule based optimizer used (consider using cbo)
Statistics
———————————————————-
1 recursive calls
0 db block gets
3 consistent gets
1 physical reads
0 redo size
752 bytes sent via SQL*Net to client
469 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
9 rows processed
RBO模式下,仍然要做SORT,使用的是 SORT UNIQUE
SQL> show parameters opt
NAME TYPE VALUE
———————————— ———– ——————————
optimizer_features_enable string 10.2.0.1
optimizer_mode string RULE
SQL> alter session set optimizer_mode = choose;
Session altered.
SQL> analyze table t compute statistics;
Table analyzed.
SQL> select distinct password from t;
Execution Plan
———————————————————-
Plan hash value: 1901613472
—————————————————————————
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
—————————————————————————
| 0 | SELECT STATEMENT | | 9 | 144 | 3 (34)| 00:00:01 |
| 1 | HASH UNIQUE | | 9 | 144 | 3 (34)| 00:00:01 |
| 2 | TABLE ACCESS FULL| T | 9 | 144 | 2 (0)| 00:00:01 |
—————————————————————————
Statistics
———————————————————-
1 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
752 bytes sent via SQL*Net to client
469 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
9 rows processed
HASH UNIQUE避免了排序,在数据量很大的时候应该能够看到较低的%CPU COST
SQL> ALTER SESSION SET “_gby_hash_aggregation_enabled” = FALSE;
SQL> select distinct password from t;
Execution Plan
———————————————————-
Plan hash value: 965418380
—————————————————————————
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
—————————————————————————
| 0 | SELECT STATEMENT | | 9 | 144 | 3 (34)| 00:00:01 |
| 1 | SORT UNIQUE | | 9 | 144 | 3 (34)| 00:00:01 |
| 2 | TABLE ACCESS FULL| T | 9 | 144 | 2 (0)| 00:00:01 |
—————————————————————————
Statistics
———————————————————-
1 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
752 bytes sent via SQL*Net to client
469 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
9 rows processed
_gby_hash_aggregation_enabled决定默认使用哪种方式执行DISTINCT.



















有启发.
你从哪里找到 “_gby_hash_aggregation_enabled” 这个东西的?
订阅asktom每天最新的Post,看到有人问Unique和Distinct的区别。Tom回答涉及到10g中的这个minor change。 然后google HASH UNIQUE 可以看到相关的资料找到这个隐藏参数。
另外我设置optimizer_features_enable=9.2.0作测试,使用的SORT UNIQUE,也可以观察到哪些cbo参数的不同。
不知道oracle采用hash unique是采用什么算法的。
如果只是做hash函数计算hash value的话, 那如何克服collision呢?
1)
10.1 没有这个参数, 10.2 才有
SELECT * FROM x$ksppi WHERE KSPPINM LIKE ‘%hash%aggregation%’;
2)
怎样观察那些cbo参数 ? 你是用以下 SELECT 查询吗?
select
child_number, name, value
from v$sql_optimizer_env
where
sql_id = ‘g4pkmrqrgxg3b’
order by
child_number,
name
;
http://jonathanlewis.wordpress.com/2007/05/01/optimizer-environment/
3) 奇怪的sort使用情况:
当我 disable “_gby_hash_aggregation_enabled”以后, sorts (memory) 还是 0 , 乖乖.
执行计划路径倒是改成了 SORT UNIQUE
sys@fin_vicintdb01> ALTER SESSION SET “_gby_hash_aggregation_enabled” = FALSE;
Session altered.
scott@fin_vicintdb01>select distinct job from scott.emp;
JOB
———
CLERK
SALESMAN
PRESIDENT
MANAGER
ANALYST
Elapsed: 00:00:00.01
Execution Plan
———————————————————-
Plan hash value: 596748738
—————————————————————————
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
—————————————————————————
| 0 | SELECT STATEMENT | | 5 | 40 | 4 (25)| 00:00:01 |
| 1 | SORT UNIQUE | | 5 | 40 | 4 (25)| 00:00:01 |
| 2 | TABLE ACCESS FULL| EMP | 15 | 120 | 3 (0)| 00:00:01 |
—————————————————————————
Statistics
———————————————————-
0 recursive calls
0 db block gets
7 consistent gets
0 sorts (memory)
0 sorts (disk)
5 rows processed
补充一下,
在Oracle 10.1中, 有一个排序操作.
1 sorts (memory)