oracle 排序太慢,Oracle 排序优化
2015年5月20日19:14:43 - 排序
1. 查看排序区内存的大小以及设置
实际排序所用到的内存、磁盘的统计信息:
pga_aggregate_target:此参数用来指定所有session总计可以使用最大PGA内存 olap:50% oltp:20%
sqlSQL> show parameter pga_aggre
NAME TYPE VALUE
------------------------------------ ---------------------- ------------------------------
pga_aggregate_target big integer 0
SQL> show parameter workarea_size_policy
workarea_size_policy:此参数用于开关PGA内存自动管理功能 auto:自动分配sort_area_size 属于workarea 如果需要经常排序就需要把这个值设置大点
sqlSQL> show parameter workarea_size_policy
NAME TYPE VALUE
------------------------------------ ---------------------- ------------------------------
workarea_size_policy string AUTO
select name, value from v$sysstat where name like ‘sort%’; select * from v$pgastat;
sqlSQL> select name , value from v$sysstat where name like 'sort%';
NAME VALUE
-------------------------------------------------------------------------------------------------------------------------------- ----------
sorts (memory) 4283
sorts (disk) 0
sorts (rows) 40823
2. 比较以下操作
select * from customers;
sqlSQL> set autotrace traceonly
SQL> select * from customers;
已选择55500行。
已用时间: 00: 00: 01.93
执行计划
----------------------------------------------------------
Plan hash value: 2008213504
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 55500 | 9810K| 406 (1)| 00:00:05 |
| 1 | TABLE ACCESS FULL| CUSTOMERS | 55500 | 9810K| 406 (1)| 00:00:05 |
-------------------------------------------------------------------------------
统计信息
----------------------------------------------------------
1 recursive calls
0 db block gets
5057 consistent gets
1455 physical reads
0 redo size
10855625 bytes sent via SQL*Net to client
41109 bytes received via SQL*Net from client
3701 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
55500 rows processed
select * from customers order by cust_last_name;
sqlSQL> select * from customers order by cust_last_name;
已选择55500行。
已用时间: 00: 00: 01.93
执行计划
----------------------------------------------------------
Plan hash value: 2792773903
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 55500 | 9810K| | 2612 (1)| 00:00:32 |
| 1 | SORT ORDER BY | | 55500 | 9810K| 12M| 2612 (1)| 00:00:32 |
| 2 | TABLE ACCESS FULL| CUSTOMERS | 55500 | 9810K| | 406 (1)| 00:00:05 |
----------------------------------------------------------------------------------------
统计信息
----------------------------------------------------------
1 recursive calls
0 db block gets
1459 consistent gets
1454 physical reads
0 redo size
6278979 bytes sent via SQL*Net to client
41109 bytes received via SQL*Net from client
3701 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
55500 rows processed
可以看到使用order by用到了额外的12M内存
3. 在cust_last_name创建b*索引
没建索引:
sqlexplain plan for select cust_last_name from customers order by cust_last_name;
sqlSQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------
Plan hash value: 2792773903
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 55500 | 433K| | 610 (1)| 00:00:08 |
| 1 | SORT ORDER BY | | 55500 | 433K| 880K| 610 (1)| 00:00:08 |
| 2 | TABLE ACCESS FULL| CUSTOMERS | 55500 | 433K| | 405 (1)| 00:00:05 |
----------------------------------------------------------------------------------------
建立索引:
sqlcreate index lastname_idx on customers(cust_last_name);
sqlexplain plan for select /*+ index(c lastname_idx) */ cust_last_name from customers order by cust_last_name;
执行计划:
sqlSQL> explain plan for select /*+ index(c lastname_idx) */ cust_last_name from customers order by cust_last_name;
已解释。
已用时间: 00: 00: 00.00
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------
Plan hash value: 3470560620
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 55500 | 433K| 143 (1)| 00:00:02 |
| 1 | INDEX FULL SCAN | LASTNAME_IDX | 55500 | 433K| 143 (1)| 00:00:02 |
---------------------------------------------------------------------------------
可以发现在一列建立索引后,对该列进行排序操作不需要再执行排序操作,
他会根据索引来进行查询(索引中本来就已经排好序)
结论
建立索引可以节省排序操作的时间。
4. 查询前十条记录
通常我们都会:
sqlselect cust_last_name from customers where rownum<=20 order by 1;
sqlSQL> select cust_last_name from customers where rownum<=20 order by 1;
CUST_LAST_NAME
--------------------------------------------------------------------------------
Everett
Everett
Everett
Everett
Everett
Everett
Everett
Everett
Everett
Ruddy
Ruddy
CUST_LAST_NAME
--------------------------------------------------------------------------------
Ruddy
Ruddy
Ruddy
Ruddy
Ruddy
Ruddy
Ruddy
Ruddy
Ruddy
已选择20行。
这样是错误的,因为在oracle中where永远都是先执行的也就先取20条再排序。
正确的做法是使用子查询:
sqlselect cust_last_name from (select * from customers order by cust_last_name) where rownum<10;
sqlSQL>select cust_last_name from (select * from customers order by cust_last_name) where rownum<10;
CUST_LAST_NAME
--------------------------------------------------------------------------------
Aaron
Aaron
Aaron
Aaron
Aaron
Aaron
Aaron
Aaron
Aaron
Aaron
Aaron
CUST_LAST_NAME
--------------------------------------------------------------------------------
Aaron
Aaron
Aaron
Aaron
Aaron
Aaron
Aaron
Aaron
Aaron
已选择20行。
没建索引:
sqlPLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------
Plan hash value: 1285511559
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 9 | 198 | | 2612 (1)| 00:00:32 |
|* 1 | COUNT STOPKEY | | | | | | |
| 2 | VIEW | | 55500 | 1192K| | 2612 (1)| 00:00:32 |
|* 3 | SORT ORDER BY STOPKEY| | 55500 | 9810K| 12M| 2612 (1)| 00:00:32 |
| 4 | TABLE ACCESS FULL | CUSTOMERS | 55500 | 9810K| | 406 (1)| 00:00:05 |
---------------------------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM<10)
3 - filter(ROWNUM<10)
已选择17行。
建立索引后:
sqlPLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
Plan hash value: 3026242074
----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 9 | 198 | 4 (0)| 00:00:01 |
|* 1 | COUNT STOPKEY | | | | | |
| 2 | VIEW | | 9 | 198 | 4 (0)| 00:00:01 |
| 3 | INDEX FULL SCAN| LASTNAME_IDX | 9 | | 2 (0)| 00:00:01 |
----------------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM<10)
已选择15行。
建立索引后,子查询效率明显提高
同时select cust_last_name from customers where rownum<=10 order by cust_last_name;和上面的结果已经大不相同。
sqlSQL> select cust_last_name from customers where rownum<=10 order by cust_last_name;
CUST_LAST_NAME
--------------------------------------------------------------------------------
Aaron
Aaron
Aaron
Aaron
Aaron
Aaron
Aaron
Aaron
Aaron
Aaron
已选择10行。
执行计划:
sqlSQL> explain plan for
2 select cust_last_name from customers where rownum<=10 order by cust_last_name;
已解释。
已用时间: 00: 00: 00.00
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------
Plan hash value: 2820001957
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10 | 80 | 2 (0)| 00:00:01 |
|* 1 | COUNT STOPKEY | | | | | |
| 2 | INDEX FULL SCAN| LASTNAME_IDX | 55500 | 433K| 2 (0)| 00:00:01 |
---------------------------------------------------------------------------------
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------
---------------------------------------------------
1 - filter(ROWNUM<=10)
已选择14行。
竟然不是刚刚那样乱的。
结论
建立索引能够对提高子查询的性能,并且查询前十条记录不再需要使用子查询, 因为建立好索引后已经是排好序的,只要根据索引从表中拿出前十条记录即可。
5. 分组与索引
首先先建立一个表
sqlSQL> create table s as select * from sales;
表已创建。
s表与sales表的数据完全是一致的但s表没有sales表上的索引。
然后我们看一下执行计划:
sqlSQL> explain plan for
2 select cust_id,avg(amount_sold) from s group by cust_id;
已解释。
已用时间: 00: 00: 00.23
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------
Plan hash value: 1912481676
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 785K| 19M| 1271 (4)| 00:00:16 |
| 1 | HASH GROUP BY | | 785K| 19M| 1271 (4)| 00:00:16 |
| 2 | TABLE ACCESS FULL| S | 785K| 19M| 1236 (1)| 00:00:15 |
---------------------------------------------------------------------------
Note
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------
-----
- dynamic sampling used for this statement (level=2)
已选择13行。
我们再看一下sales表(即建立了索引的表):
sqlSQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------
Plan hash value: 2820001957
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10 | 80 | 2 (0)| 00:00:01 |
|* 1 | COUNT STOPKEY | | | | | |
| 2 | INDEX FULL SCAN| LASTNAME_IDX | 55500 | 433K| 2 (0)| 00:00:01 |
---------------------------------------------------------------------------------
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------
---------------------------------------------------
1 - filter(ROWNUM<=10)
已选择14行。
结论
group by的一列上建立索引group by 性能更佳。
下面是关于order by 升序降序的执行计划可以看出建立索引升降序对排序不会影响性能
升序:
sqlSQL> select cust_last_name from customers where rownum <= 10 order by cust_last_name;
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------
Plan hash value: 2820001957
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10 | 80 | 2 (0)| 00:00:01 |
|* 1 | COUNT STOPKEY | | | | | |
| 2 | INDEX FULL SCAN| LASTNAME_IDX | 55500 | 433K| 2 (0)| 00:00:01 |
---------------------------------------------------------------------------------
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------
---------------------------------------------------
1 - filter(ROWNUM<=10)
已选择14行。
降序:
sqlSQL> select cust_last_name from customers where rownum <= 10 order by cust_last_name;
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------
Plan hash value: 1596600344
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 9 | 72 | 2 (0)| 00:00:01 |
|* 1 | COUNT STOPKEY | | | | | |
| 2 | INDEX FULL SCAN DESCENDING| LASTNAME_IDX | 55500 | 433K| 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------
---------------------------------------------------
1 - filter(ROWNUM<10)
已选择14行。
oracle 排序太慢,Oracle 排序优化相关推荐
- oracle空格太多,Oracle Sql字符串多余空格处理方法初记
(一)问题提出: 不知道大家有没有遇到过这样的情况,同样的sql在pl/sql下面执行正常,但是拷贝到表字段中,点击提交的时候老是会报ORA-01480: STR 绑定值的结尾 Null错误,如图: ...
- oracle+sql+按中文拼音排序,Oracle 中文字段进行排序的sql语句
Oracle 中文字段进行排序的sql语句 1)按笔画排序 select * from Table order by nlssort(columnName,'NLS_SORT=SCHINESE_STR ...
- oracle排序特别慢,Oracle 排序是件很有意思的事
以下的文章主要是对Oracle排序中的几种常用排序的介绍,你会发现Oracle 排序是一件很有意思的事,以下就是文章的具体内容的描述,以下是文章的具体介绍,望你浏览完以下的内容会有所收获. 按拼音排序 ...
- 数据库中自定义排序规则,Mysql中自定义字段排序规则,Oracle中自定义字段排序规则,decode函数的用法,field函数的用法
数据库中自定义排序 场景:有一张banner表,表中有一个status字段,有0, 1, 2三个状态位,我想要 1,0,2的自定义排序(这里是重点),然后再进行之上对sequence字段进行二次排序( ...
- oracle菜鸟学习之 分析函数-排序
oracle菜鸟学习之 分析函数-排序 排序函数 1.row_number:返回连续的排序,无论值是否相等 2.rank:具有相等值得行排序相同,序数值随后跳跃 3.dense_rank:具有相等值得 ...
- Oracle数据库之过滤和排序
oracle安装参照: Oracle数据库之安装教程 Oracle数据库总结: Oracle数据库之基本查询 Oracle数据库之单行函数 Oracle数据库之多行函数 Oracle数据库之多表查询 ...
- MySQL 如何实现 Oracle 的 row_number() over() 分组排序功能
文章目录 Oracle 的分组排序 MySQL 的分组排序 分析需求 创建模拟数据 SQL 实现 结果演示 Oracle 的分组排序 Oracle 的分组排序函数的语法格式如下: ROW_NUMBER ...
- oracle生成顺序编号,Oracle排序以及序号的输出 | 学步园
在一般Select语句中我们通过Order by ...Asc/Desc来进行排序.但是这种排序方式在输出时,不包含排序后的序号信息. 现在介绍一下Oracle中可以用于排序输出的方法. 1. RAN ...
- oracle和mysql查询条件排序_Oracle数据库中ORDERBY排序和查询按IN条件的顺序输出
ORDER BY非稳定的排序提一个问题: oracle在order by 排序时,是稳定排序算法吗? 发现用一个type进行排序后,做分页查询,第一页的数据和第二页的数据有重复 怀疑是order by ...
最新文章
- CMOS及CCD感光sensor的主要技术参数解析
- 今天浅谈功能测试基础
- Android学习笔记13-Acitivty与Fragment通信
- 后端传给前端 无限极分类_学徒|记者亲身体验垃圾分拣,臭到崩溃!我们还有什么理由不做垃圾分类?...
- VTK:图表之ColorEdges
- k8s的list-watch机制和 pod调度约束
- Angular本地数据存储LocalStorage
- python try 异常处理 史上最全
- 离线登陆_iphone手机,苹果手机如何登陆网易163邮箱
- linux 查看cuda版本_Ubuntu18.04+Tensorflow GPU版本环境搭建
- 在leangoo里怎么添加泳道?
- OCJP考试习题(1z0-808)(一)
- EPLAN电气设计入门学习笔记
- wordpress设置首页为特定页
- git 设置代理的方法
- 软件工程小组需求分析--快递代领
- torch.bmm() 与 torch.matmul()
- Trying to start MapKit location updates without prompting for location authorization. Must call -[CL
- JavaScript刮奖效果(jquery图片刮奖插件)
- application.yaml配置详解