相信做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/

SORT UNIQUE|AGGREGATE|GROUP BY|ORDER BY|JOIN的更多相关文章

  1. mongodb的聚合aggregate|group|match|project|sort|limit|skip|unwind

    聚合 aggregate 聚合(aggregate)主要用于计算数据,类似sql中的sum().avg() 语法 db.集合名称.aggregate([{管道:{表达式}}]) 管道 管道在Unix和 ...

  2. 学习mongo系列(七)aggregate() ,$group() 管道

    aggregate()聚合,主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果.有点类似sql语句中的 count(*) 接上边的数据库: > db.user.aggregate ...

  3. MySql学习(二) —— where / having / group by / order by / limit 简单查询

    注:该MySql系列博客仅为个人学习笔记. 这篇博客主要记录sql的五种子句查询语法! 一个重要的概念:将字段当做变量看,无论是条件,还是函数,或者查出来的字段. select五种子句 where 条 ...

  4. Hash unique和Sort unique

    SQL> set linesize 200 SQL> set pagesize 200 SQL> set autot trace SQL> select distinct de ...

  5. 【MySQL】sort by then group by

    tb: ### 需求:根据id进行分组,找到分组内hour中最大的一项 错误写法: select id, max(hour) from tb group by id; 正确的写法: ### 需求:根据 ...

  6. Aggregate (GROUP BY) Function Descriptions

    w Table 13.25 Aggregate (GROUP BY) Functions Name Description AVG() Return the average value of the ...

  7. 一次 group by + order by 性能优化分析

    一次 group by + order by 性能优化分析 最近通过一个日志表做排行的时候发现特别卡,最后问题得到了解决,梳理一些索引和MySQL执行过程的经验,但是最后还是有5个谜题没解开,希望大家 ...

  8. ORA-24408: could not generate unique server group name

    一台新虚拟机,CentOS 6.5系统,用lnmp一键安装包安装好Nginx + PHP环境,再安装Oracle客户端,准备搭建PHP连接Oracle,访问oracle.php,测试连接Oracle的 ...

  9. where / having / group by / order by / limit 简单查询

    目录 1.基础查询 -- where 2. group by 与 统计函数 3. having 4.where + group by + having + 函数 综合查询 5. order by + ...

随机推荐

  1. Centos环境下部署游戏服务器-Eclipse

    一直在想这篇文章该不该写,因为这篇文章更像是教你如何使用一个ide这种文章,毫无价值可言.但思来想去还是应给写.上篇文章主要说了编译原理和过程,这篇文章就是理论联系实际的典范.并且很多工程师一辈子都不 ...

  2. VCL定义和使用CM_Message的原因(主要是内部控制,同时可简化参数传递,还可截住消息,统一走消息路线,还可省内存)

    内部控制是指,做了某些操作后产生某些效果,但是Windows系统本身不提供这样的消息,应此不得不自定义.比如父窗口改变了字体,那么所有子窗口也都应该改变字体,至少也得通知一下它们,让子控件自己决定是否 ...

  3. Array.prototype.slice.call(document.querySelectorAll('a'), 0)

    Array.prototype.slice.call(document.querySelectorAll('a'), 0)的作用就是将一个DOM NodeList 转换成一个数组. slice()方法 ...

  4. iOS Architecture

    目前ios的指令集有以下几种: armv6 iPhone iPhone2 iPhone3G 第一代和第二代iPod Touch armv7 iPhone4 iPhone4S armv7s iPhone ...

  5. java string,需要进行首字母大写改写

    java string,需要进行首字母大写改写,网上大家的思路基本一致,就是将首字母截取,转化成大写然后再串上后面的,类似如下代码 //首字母大写     public static String c ...

  6. PHP中对数据库操作的封装

    在动态网面设计中很多都要涉及到对数据库的操作,但是有时跟据需要而改用其它后台数据库,就需要大量修改程序.这是一件枯燥.费时而且容易出错的功作.其实我们可以用PHP中的类来实现对数据库操作的封装,从而使 ...

  7. Linux中__init、__devinit等内核优化宏【转】

    转自:http://blog.csdn.net/joker0910/article/details/7171626 内核使用了大量不同的宏来标记具有不同作用的函数和数据结构.如宏__init .__d ...

  8. hdoj - 5202 Rikka with string (BestCoder Round #37 ($))

    http://acm.hdu.edu.cn/showproblem.php?pid=5202 字符串处理的题,要细心. 给定一个只包含小写字母和问号的字符串,让我们还原出本来的字符串,把问号替换成任意 ...

  9. 利用正则表达式去掉html代码

    using System.Text.RegularExpressions; // 利用正则表达式去掉"<"和">"之间的内容. private st ...

  10. 不同浏览器JS获取浏览器高度和宽度

    摘自:http://blog.csdn.net/lai_gb/archive/2009/07/04/4320956.aspx IE中: document.body.clientWidth ==> ...