HASH (UNIQUE) in Oracle10g

April 11th, 2007 | Categories: Boring | Tags:

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.

Del.icio.us Google书签 Digg Live Bookmark Technorati Furl Yahoo书签 Facebook 百度搜藏 新浪 ViVi 365Key 网摘 天极网摘 和讯网摘 博拉网 POCO 网摘 饭否 QQ 书签 Digbuzz 我挖网 Mister Wong
  1. 木匠
    April 12th, 2007 at 12:09
    Quote | #1

    有启发.

    你从哪里找到 “_gby_hash_aggregation_enabled” 这个东西的?

  2. 玉面飞龙
    April 12th, 2007 at 16:09
    Quote | #2

    订阅asktom每天最新的Post,看到有人问Unique和Distinct的区别。Tom回答涉及到10g中的这个minor change。 然后google HASH UNIQUE 可以看到相关的资料找到这个隐藏参数。

    另外我设置optimizer_features_enable=9.2.0作测试,使用的SORT UNIQUE,也可以观察到哪些cbo参数的不同。

  3. logzgh
    April 15th, 2007 at 22:06
    Quote | #3

    不知道oracle采用hash unique是采用什么算法的。
    如果只是做hash函数计算hash value的话, 那如何克服collision呢?

  4. 木匠
    May 11th, 2007 at 01:40
    Quote | #4

    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

  5. 木匠
    May 11th, 2007 at 01:41
    Quote | #5

    补充一下,
    在Oracle 10.1中, 有一个排序操作.
    1 sorts (memory)