zoukankan      html  css  js  c++  java
  • SORT UNIQUE|AGGREGATE|GROUP BY|ORDER BY|JOIN

    相信做oracle开发和管理的朋友对sort肯定不会陌生,大家通常都遇到这样那样的排序性能问题,所以我写这一系列关于sort的文章告诉大家在oracle里面sort是怎么一回事以及如果调整sort获得更好的性能。

    首先,我们来回顾一下什么情况下需要sort,当取distinct值的时候需要,当进行merge join的时候也需要,当语句包含group by,order by的时候需要,当创建索引的时候需要等等。那么我们来看一下在oracle里面排序分为哪几种方式呢?

    一.SORT UNIQUE : 发生在我们需要取distinct值的时候 , 也会发生在in的子查询里

    sort unique发生在我们需要取distinct值的时候

    SQL> set autotrace trace exp;
    SQL> select distinct owner from test;
    Execution Plan
    ———————————————————-
    0 SELECT STATEMENT Optimizer=CHOOSE (Cost=477 Card=15 Bytes=75
    )
    1 0 SORT (UNIQUE) (Cost=477 Card=15 Bytes=75)
    2 1 TABLE ACCESS (FULL) OF ‘TEST’ (Cost=257 Card=193488 Byte
    s=967440)

    Statistics
    ———————————————————-
    0 recursive calls
    0 db block gets
    2649 consistent gets
    0 physical reads
    0 redo size
    564 bytes sent via SQL*Net to client
    503 bytes received via SQL*Net from client
    2 SQL*Net roundtrips to/from client
    1 sorts (memory)
    0 sorts (disk)
    15 rows processed

    也会发生在in的子查询里

    SQL> select owner from test where object_id in(select object_id from test1 where rownum<10);
    Execution Plan
    ———————————————————-
    0 SELECT STATEMENT Optimizer=CHOOSE (Cost=530 Card=145116 Byte
    s=3047436)
    1 0 HASH JOIN (Cost=530 Card=145116 Bytes=3047436)
    2 1 VIEW OF ‘VW_NSO_1′ (Cost=256 Card=9 Bytes=117)
    3 2 SORT (UNIQUE)
    4 3 COUNT (STOPKEY)
    5 4 TABLE ACCESS (FULL) OF ‘TEST1′ (Cost=256 Card=1934
    88 Bytes=580464)
    6 1 TABLE ACCESS (FULL) OF ‘TEST’ (Cost=257 Card=193488 Byte
    s=1547904)

    为什么in子查询需要排序呢,因为oracle会把基于in的子查询
    “select owner from test where object_id in(select object_id from test1)”
    转换为类似
    “select a.owner from test a,(select distinct object_id from test1) b where a.object_id=b.object_id”
    如果in子查询里面选出的值可以通过主键或unique索引搜索得到,那么将不会进行sort unique的操作。

    但自从10g R2开始,sort unique有了一些变化,sort unique变成了hash unique,采用新的hash算法代替了传统的sort unique,据oracle称在某些情况下排序性能是原来的5倍。

    注意,sort的统计值将为0
    SQL> select distinct owner from test;

    Statistics
    ———————————————————-
    0 recursive calls
    0 db block gets
    692 consistent gets
    0 physical reads
    0 redo size
    781 bytes sent via SQL*Net to client
    396 bytes received via SQL*Net from client
    3 SQL*Net roundtrips to/from client
    0 sorts (memory)
    0 sorts (disk)
    19 rows processed

    SQL> select distinct owner from test;
    Execution Plan
    ———————————————————-
    Plan hash value: 2203132549
    —————————————————————————
    | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    —————————————————————————
    | 0 | SELECT STATEMENT | | 19 | 95 | 164 (5)| 00:00:02 |
    | 1 | HASH UNIQUE | | 19 | 95 | 164 (5)| 00:00:02 |
    | 2 | TABLE ACCESS FULL| TEST | 49909 | 243K| 158 (2)| 00:00:02 |
    ————————————————————————–

    SQL> select owner from test where object_id in(select object_id from test1 where rownum<10);
    Execution Plan
    ———————————————————-
    Plan hash value: 2420636264
    ——————————————————————————–
    ——————
    | Id | Operation | Name | Rows | Bytes | Cost
    (%CPU)| Time |
    ——————————————————————————–
    ——————
    | 0 | SELECT STATEMENT | | 5989 | 116K| 284
    (2)| 00:00:04 |
    | 1 | TABLE ACCESS BY INDEX ROWID| TEST | 665 | 4655 | 14
    (0)| 00:00:01 |
    | 2 | NESTED LOOPS | | 5989 | 116K| 284
    (2)| 00:00:04 |
    | 3 | VIEW | VW_NSO_1 | 9 | 117 | 156
    (2)| 00:00:02 |
    | 4 | HASH UNIQUE | | 9 | 18 |
    | |
    |* 5 | COUNT STOPKEY | | | |
    | |
    | 6 | TABLE ACCESS FULL | TEST1 | 49909 | 99818 | 156
    (2)| 00:00:02 |
    |* 7 | INDEX RANGE SCAN | IND_TEST_OBJECT_ID | 665 | | 2
    (0)| 00:00:01 |

    二.SORT AGGREGATE
    sort aggregate通常发生在使用一些聚合函数的时候,sum(),avg(),min(),max(),count()等等,实际上sort aggregate不做真正的sort,并不会用到排序空间,而是通过一个全局变量+全表或全索引扫描来实现。伪代码如下
    max_so_far = -INFINITE;
    while (row* r=get_a_row_from_table(test_for_max)) {
    if (r->n > max_so_far) max_so_far=n;
    }
    return max_so_far

    SQL> select count(*) from test;
    Execution Plan
    ———————————————————-
    0 SELECT STATEMENT Optimizer=CHOOSE (Cost=257 Card=1)
    1 0 SORT (AGGREGATE)
    2 1 TABLE ACCESS (FULL) OF ‘TEST’ (Cost=257 Card=193488)

    SQL> select sum(object_id) from test;
    Execution Plan
    ———————————————————-
    0 SELECT STATEMENT Optimizer=CHOOSE (Cost=257 Card=1 Bytes=3)
    1 0 SORT (AGGREGATE)
    2 1 TABLE ACCESS (FULL) OF ‘TEST’ (Cost=257 Card=193488 Byte
    s=580464)

    SQL> select min(object_id) from test;
    Execution Plan
    ———————————————————-
    0 SELECT STATEMENT Optimizer=CHOOSE (Cost=257 Card=1 Bytes=3)
    1 0 SORT (AGGREGATE)
    2 1 INDEX (FULL SCAN (MIN/MAX)) OF ‘IND_TEST_OBJECT_ID’ (NON
    -UNIQUE) (Cost=257 Card=193488 Bytes=580464)

    SQL> select max(object_id) from test;
    Execution Plan
    ———————————————————-
    0 SELECT STATEMENT Optimizer=CHOOSE (Cost=257 Card=1 Bytes=3)
    1 0 SORT (AGGREGATE)
    2 1 INDEX (FULL SCAN (MIN/MAX)) OF ‘IND_TEST_OBJECT_ID’ (NON
    -UNIQUE) (Cost=257 Card=193488 Bytes=580464)

    SQL> select avg(object_id) from test;
    Execution Plan
    ———————————————————-
    0 SELECT STATEMENT Optimizer=CHOOSE (Cost=257 Card=1 Bytes=3)
    1 0 SORT (AGGREGATE)
    2 1 TABLE ACCESS (FULL) OF ‘TEST’ (Cost=257 Card=193488 Byte
    s=580464)

    SQL> select count(*) from test;

    Statistics
    ———————————————————-
    0 recursive calls
    0 db block gets
    2649 consistent gets
    0 physical reads
    0 redo size
    381 bytes sent via SQL*Net to client
    503 bytes received via SQL*Net from client
    2 SQL*Net roundtrips to/from client
    0 sorts (memory)
    0 sorts (disk)
    1 rows processed

    三.SORT GROUP BY
    SORT GROUP BY会发生在有group by子句的时候

    SQL> select owner from test group by owner;
    15 rows selected.

    Execution Plan
    ———————————————————-
    0 SELECT STATEMENT Optimizer=CHOOSE (Cost=477 Card=15 Bytes=75
    )
    1 0 SORT (GROUP BY) (Cost=477 Card=15 Bytes=75)
    2 1 TABLE ACCESS (FULL) OF ‘TEST’ (Cost=257 Card=193488 Byte
    s=967440)

    Statistics
    ———————————————————-
    0 recursive calls
    0 db block gets
    2649 consistent gets
    0 physical reads
    0 redo size
    564 bytes sent via SQL*Net to client
    503 bytes received via SQL*Net from client
    2 SQL*Net roundtrips to/from client
    1 sorts (memory)
    0 sorts (disk)
    15 rows processed

    在10g R2里又有了变化,sort group by被hash group by所代替
    SQL> select owner from test group by owner;
    19 rows selected.

    Execution Plan
    ———————————————————-
    Plan hash value: 1435881708
    —————————————————————————
    | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    —————————————————————————
    | 0 | SELECT STATEMENT | | 19 | 95 | 164 (5)| 00:00:02 |
    | 1 | HASH GROUP BY | | 19 | 95 | 164 (5)| 00:00:02 |
    | 2 | TABLE ACCESS FULL| TEST | 49909 | 243K| 158 (2)| 00:00:02 |
    —————————————————————————

    Statistics
    ———————————————————-
    1 recursive calls
    0 db block gets
    692 consistent gets
    0 physical reads
    0 redo size
    781 bytes sent via SQL*Net to client
    396 bytes received via SQL*Net from client
    3 SQL*Net roundtrips to/from client
    0 sorts (memory)
    0 sorts (disk)
    19 rows processed
    联想到上面提到的sort unique也是被hash unique所代替,我们可以肯定10g R2用了更多基于hash算法的东西,我们也期待在数据库其他方面10g R2也带给我们更多的好处。

    四.SORT ORDER BY
    SORT ORDER BY会发生在有order by子句的时候

    SQL> select owner from test order by owner;
    193488 rows selected.

    Execution Plan
    ———————————————————-
    0 SELECT STATEMENT Optimizer=CHOOSE (Cost=666 Card=193488 Byte
    s=967440)
    1 0 SORT (ORDER BY) (Cost=666 Card=193488 Bytes=967440)
    2 1 TABLE ACCESS (FULL) OF ‘TEST’ (Cost=257 Card=193488 Byte
    s=967440)

    Statistics
    ———————————————————-
    0 recursive calls
    0 db block gets
    2649 consistent gets
    0 physical reads
    0 redo size
    2528735 bytes sent via SQL*Net to client
    142392 bytes received via SQL*Net from client
    12901 SQL*Net roundtrips to/from client
    1 sorts (memory)
    0 sorts (disk)
    193488 rows processed

    五.SORT JOIN
    SORT JOIN发生在出现merge join的情况下,两张关联的表要各自做sort,然后再merge

    SQL> select /*+ use_merge(a b)*/ a.owner from test a,test1 b where a.object_id=b.object_id and rownum<10;
    9 rows selected.

    Execution Plan
    ———————————————————-
    0 SELECT STATEMENT Optimizer=CHOOSE (Cost=1354 Card=9 Bytes=99
    )
    1 0 COUNT (STOPKEY)
    2 1 MERGE JOIN (Cost=1354 Card=3119800512 Bytes=34317805632)
    3 2 SORT (JOIN) (Cost=737 Card=193488 Bytes=1547904)
    4 3 TABLE ACCESS (FULL) OF ‘TEST’ (Cost=257 Card=193488
    Bytes=1547904)
    5 2 SORT (JOIN) (Cost=617 Card=193488 Bytes=580464)
    6 5 TABLE ACCESS (FULL) OF ‘TEST1′ (Cost=256 Card=193488
    Bytes=580464)

    Statistics
    ———————————————————-
    0 recursive calls
    0 db block gets
    5251 consistent gets
    0 physical reads
    0 redo size
    444 bytes sent via SQL*Net to client
    503 bytes received via SQL*Net from client
    2 SQL*Net roundtrips to/from client
    2 sorts (memory)
    0 sorts (disk)

    转载:http://blog.163.com/cyh_1987/blog/static/39469292012922103927464/

  • 相关阅读:
    MySQL数据库的安装与配置
    java中的反射机制
    详谈设计模式之单列模式
    servlet内部转发与重定向
    servlet基础语句总结
    Servlet映射的俩种方法以及优缺点
    eclipse和idea的快捷键比较及idea如何调节eclipse的快捷键
    servlet
    JDK下载与安装教程
    正则表达式查询
  • 原文地址:https://www.cnblogs.com/future2012lg/p/3226535.html
Copyright © 2011-2022 走看看