相信做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. 注册表修改PSD关联photoshop

    当psd文件右键点击--打开方式--选择默认程序photoshop也没用的时候,那应该是注册表未关联,可以试下以下方法: 第一步:在运行框中输入regedit,打开注册表编辑器,将HKEY_CLASS ...

  2. [iOS]ios archives 出现的是other items而不是iOS Apps的解决方案

    百度了一上午, 总是这样子. (利用cocoapods上传项目的时候, 总是这样无法点击UpLoad to App Store) 然后. 这样做. 就可以了!

  3. iOS:核心动画之转场动画CATransition

    转场动画——CATransition CATransition是CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果.iOS比Mac OS X的转场动画效果少一点 U ...

  4. 移动设备中导入gdb调试工具

    (1)概述 接ADB调试桥安装(方式一),ADB调试桥安装好了后一般的移动设备内都不含有gdb工具, 要想使用gdb工具可以借助adb的push参数进行上传. gdb分为gdb客户端和服务端,文件可以 ...

  5. z-index无效问题的解决方法

    在使用z-index这个属性之前,我们必须先了解使用z-index的必要条件: 1.要想给元素设置z-index样式,必须先让它变成定位元素,说的明白一点,就是要给元素设置一个postion:rela ...

  6. Seajs demo

    index.html <!doctype html> <html lang="en"> <head> <meta charset=&quo ...

  7. Android eclipse中程序调试

    一:断点调试 用eclipse开发android程序的时,跟VS一样是可以断点单步调试的.步骤如下.1 设置断点:在编码窗体的左边框上用鼠标双击,或者右键点击菜单,选择 Toggle Breakpoi ...

  8. linux中/etc/init.d [转]

    一.关于/etc/init.d 如果你使用过linux系统,那么你一定听说过init.d目录.这个目录到底是干嘛的呢?它归根结底只做了一件事情,但这件事情非同小可,是为整个系统做的,因此它非常重要.i ...

  9. Google 网络库Volley简介

    Volley是什么? 2013 Google I/O 大会发布的Android平台网络通讯库,旨在帮助开发者实现更快速,简单,健壮的网络通讯.支持网络图片的缓存加载功能. 适用场景:数据量不大,但是通 ...

  10. hdu4427Math Magic

    4427 dp[i][j][k] i为K位的最小公倍数 j为k位的和 k以滚动数组的形式 这题最棒的是 有一个强有力的剪枝 组成公倍数m的肯定都是M的质因子 这样1000里面最多就30多个 复杂度可过 ...