相信做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. 替换应用程序exe图标,主要使用BeginUpdateResource,UpdateResource API函数

    替换应用程序exe图标,主要使用的API函数是BeginUpdateResource(),UpdateResource(),EndUpdateResource()来使用自定义的ico文件类替换exe程 ...

  2. 利用Hessian如何实现Webservice

    利用Hessian如何实现Webservice [大] [中] [小] 发布人:圣才学习网  发布日期:2012-08-18 14:02  共966人浏览 Hessian是 一个轻量级的remotin ...

  3. iphone/ipad实现自定义的开关UISwitch(continuous,clipsToBounds,userInteractionEnabled属性)

    这里主要讲几个UIView的几个属性,具体大家可以下载代码看看, 下载地址是: http://download.csdn.net/detail/rhljiayou/5960003 实现效果是: 代码中 ...

  4. sed文本处理知识点整理

    参考资料:http://man.linuxde.net/sed    <鸟哥的私房菜> sed是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用.sed 后面接的操作 ...

  5. [原]poj-2680-Choose the best route-dijkstra(基础最短路)

    题目大意: 已知n 个点,m条路线,s为终点:给出m条路线及其权值:给出w个起点,求最短路! 思路:基础的dijkstra,有向无环正权最短路,只要把终点和起点 reverse考虑便可. AC代码如下 ...

  6. make clean vs make clobber

    make is pretty smart, and picks up what has changed from the last build, so if you run repo sync and ...

  7. [androd] android的在线源码网站,各个版本都有(目前已到俺android 4.2,但不包含kernel部分的代码)

    android的在线源码阅读网站,各个版本都有(目前最新版本已到android 4.2,但不包含kernel部分的代码) 这个网站最大的特点是:可以在网页上方的搜索框,搜索整个网站所存储的源码中的字符 ...

  8. BZOJ 2038 小Z的袜子(hose)(分组)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2038 题意:给出n个袜子.m个询问,每个询问一个区间[L,R],询问这个区间中任意拿出两 ...

  9. 总结Selenium自动化测试方法(六)常见的异常错误处理

    六.常见的异常错误处理 NoSuchElementException: Message: Unable to locate element: {"method":"xpa ...

  10. noi2015的回忆和教训

    前几天偶然打开了bzoj的rank list,突然发现——我竟然掉出了第一版!!! 自从我5月还是6月刷进第一版之后,我曾经天真的以为大概半年之内我还能保留在第一版内吧. 结果仅仅短短的4个月,我就已 ...