--原SQL 语句如下:
select *
from (select tmp_tb.*, ROWNUM row_id
from (select wpid,
customer_id,
customer_name,
gender,
to_char(wi.call_time, 'yyyy-mm-dd hh24:mi:ss') call_time,
call_num,
phoneno,
tel,
cardtype,
cardnum,
note,
sessionid,
(select c.nodevalue
from sys_code c
where c.auto_id = wi.wp_type) wp_type,
smalltype,
order_type,
priority,
is_callback,
is_hidden,
district,
address,
summary,
wp_title,
wp_remark,
(select c.nodename
from sys_code c
where c.auto_id = wi.wp_source) wp_source,
(select c.nodevalue
from sys_code c
where c.auto_id = wi.class1) class1,
(select c.nodevalue
from sys_code c
where c.auto_id = wi.class2) class2,
(select c.nodevalue
from sys_code c
where c.auto_id = wi.class3) class3,
(select c.nodevalue
from sys_code c
where c.auto_id = wi.class4) class4,
upload_acceptance,
upload_handle,
upload_back,
upload_supervise,
is_repeat,
to_char(wi.starttime, 'yyyy-mm-dd hh24:mi:ss') starttime,
sender,
to_char(wi.updatetime, 'yyyy-mm-dd hh24:mi:ss') updatetime,
lastmessage,
(select sf.statename
from sys_function sf
where sf.auto_id = wi.state) state,
(select sf.statename
from sys_function sf
where sf.auto_id = wi.next_state) next_state,
next_state next_state_id,
dept_center,
(select stu.stru_name
from sys_stru stu
where stu.auto_id = wi.dept_level1) dept_level1,
(select stu.stru_name
from sys_stru stu
where stu.auto_id = wi.dept_level2) dept_level2,
(select stu.stru_name
from sys_stru stu
where stu.auto_id = wi.dept_level3) dept_level3,
(select stu.stru_name
from sys_stru stu
where stu.auto_id = wi.dept_cooperate1) dept_cooperate1,
(select stu.stru_name
from sys_stru stu
where stu.auto_id = wi.dept_cooperate2) dept_cooperate2,
is_reminder,
is_supervise,
is_overtime,
is_review,
to_char(wi.send_time, 'yyyy-mm-dd hh24:mi:ss') send_time,
to_char(wi.time_boundry, 'yyyy-mm-dd hh24:mi:ss') time_boundry,
source_address,
ciid1,
ciid2,
complaintname,
complainttel,
compensate_money,
back_source,
donereport,
reply_point,
to_char(wi.reply_time, 'yyyy-mm-dd hh24:mi:ss') reply_time,
solved,
passoperator,
to_char(wi.donetime, 'yyyy-mm-dd hh24:mi:ss') donetime,
dept_workno,
specialSeat_type,
to_char(wi.acceptTime_boundry, 'yyyy-mm-dd hh24:mi:ss') acceptTime_boundry,
to_char(wi.acceptTime, 'yyyy-mm-dd hh24:mi:ss') acceptTime,
orderSymbol,
timeout_flag,
send_flag,
getLastWorknoByWpid(wi.wpid) operatorno,
is_relation,
(select count(1)
from wp_info wp
where wp.relation_wpid = wi.wpid) total,
ep_flag,
is_difficult,
(select count(1)
from wp_early_warning_info
where wpid = wi.wpid) lid,
endresult
from xxx_info wi
where 1 = 1
order by wi.starttime desc) tmp_tb
where ROWNUM <= 10)
where row_id > 0
--执行时间 147s
通过 explain plan for 上述语句,获取其执行计划
select * from table(dbms_xplan.display()); PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 964360475 ---------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10 | 116K| | 205K (1)| 00:41:04 |
| 1 | TABLE ACCESS BY INDEX ROWID| SYS_CODE | 1 | 17 | | 2 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | SYS_C005980 | 1 | | | 1 (0)| 00:00:01 |
| 3 | TABLE ACCESS BY INDEX ROWID| SYS_CODE | 1 | 17 | | 2 (0)| 00:00:01 |
|* 4 | INDEX UNIQUE SCAN | SYS_C005980 | 1 | | | 1 (0)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID| SYS_CODE | 1 | 17 | | 2 (0)| 00:00:01 |
|* 6 | INDEX UNIQUE SCAN | SYS_C005980 | 1 | | | 1 (0)| 00:00:01 |
| 7 | TABLE ACCESS BY INDEX ROWID| SYS_CODE | 1 | 17 | | 2 (0)| 00:00:01 |
|* 8 | INDEX UNIQUE SCAN | SYS_C005980 | 1 | | | 1 (0)| 00:00:01 |
| 9 | TABLE ACCESS BY INDEX ROWID| SYS_CODE | 1 | 17 | | 2 (0)| 00:00:01 |
|* 10 | INDEX UNIQUE SCAN | SYS_C005980 | 1 | | | 1 (0)| 00:00:01 |
| 11 | TABLE ACCESS BY INDEX ROWID| SYS_CODE | 1 | 17 | | 2 (0)| 00:00:01 |
|* 12 | INDEX UNIQUE SCAN | SYS_C005980 | 1 | | | 1 (0)| 00:00:01 |
| 13 | TABLE ACCESS BY INDEX ROWID| SYS_FUNCTION | 1 | 15 | | 1 (0)| 00:00:01 |
|* 14 | INDEX UNIQUE SCAN | SYS_FUNC_ID | 1 | | | 0 (0)| 00:00:01 |
| 15 | TABLE ACCESS BY INDEX ROWID| SYS_FUNCTION | 1 | 15 | | 1 (0)| 00:00:01 |
|* 16 | INDEX UNIQUE SCAN | SYS_FUNC_ID | 1 | | | 0 (0)| 00:00:01 |
| 17 | TABLE ACCESS BY INDEX ROWID| SYS_STRU | 1 | 21 | | 2 (0)| 00:00:01 |
|* 18 | INDEX UNIQUE SCAN | STRU_ID_PK | 1 | | | 1 (0)| 00:00:01 |
| 19 | TABLE ACCESS BY INDEX ROWID| SYS_STRU | 1 | 21 | | 2 (0)| 00:00:01 |
|* 20 | INDEX UNIQUE SCAN | STRU_ID_PK | 1 | | | 1 (0)| 00:00:01 |
| 21 | TABLE ACCESS BY INDEX ROWID| SYS_STRU | 1 | 21 | | 2 (0)| 00:00:01 |
|* 22 | INDEX UNIQUE SCAN | STRU_ID_PK | 1 | | | 1 (0)| 00:00:01 |
| 23 | TABLE ACCESS BY INDEX ROWID| SYS_STRU | 1 | 21 | | 2 (0)| 00:00:01 |
|* 24 | INDEX UNIQUE SCAN | STRU_ID_PK | 1 | | | 1 (0)| 00:00:01 |
| 25 | TABLE ACCESS BY INDEX ROWID| SYS_STRU | 1 | 21 | | 2 (0)| 00:00:01 |
|* 26 | INDEX UNIQUE SCAN | STRU_ID_PK | 1 | | | 1 (0)| 00:00:01 |
| 27 | SORT AGGREGATE | | 1 | 2 | | | |
|* 28 | INDEX RANGE SCAN | IDX_WPINFO_RELATIONWPID | 32 | 64 | | 1 (0)| 00:00:01 |
| 29 | SORT AGGREGATE | | 1 | 15 | | | |
|* 30 | INDEX RANGE SCAN | IDX_WEWI_WPID | 1 | 15 | | 1 (0)| 00:00:01 |
|* 31 | VIEW | | 10 | 116K| | 205K (1)| 00:41:04 |
|* 32 | COUNT STOPKEY | | | | | | |
| 33 | VIEW | | 1051K| 11G| | 205K (1)| 00:41:04 |
|* 34 | SORT ORDER BY STOPKEY | | 1051K| 778M| 1026M| 205K (1)| 00:41:04 |
| 35 | TABLE ACCESS FULL | WP_INFO | 1051K| 778M| | 33545 (1)| 00:06:43 |
--------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id):
--------------------------------------------------- 2 - access("C"."AUTO_ID"=TO_NUMBER(:B1))
4 - access("C"."AUTO_ID"=TO_NUMBER(:B1))
6 - access("C"."AUTO_ID"=TO_NUMBER(:B1))
8 - access("C"."AUTO_ID"=TO_NUMBER(:B1))
10 - access("C"."AUTO_ID"=TO_NUMBER(:B1))
12 - access("C"."AUTO_ID"=TO_NUMBER(:B1))
14 - access("SF"."AUTO_ID"=TO_NUMBER(:B1))
16 - access("SF"."AUTO_ID"=TO_NUMBER(:B1))
18 - access("STU"."AUTO_ID"=:B1)
20 - access("STU"."AUTO_ID"=:B1)
22 - access("STU"."AUTO_ID"=:B1)
24 - access("STU"."AUTO_ID"=:B1)
26 - access("STU"."AUTO_ID"=:B1)
28 - access("WP"."RELATION_WPID"=:B1)
30 - access("WPID"=:B1)
31 - filter("ROW_ID">0)
32 - filter(ROWNUM<=10)
34 - filter(ROWNUM<=10) 该语句看起来挺长,但主要还是从WP_INFO 表取数据,无其他where条件限制,根据starttime 对全表倒序排序,取前十
执行计划看出WP_INFO表 行数1051K ,全表扫描,排序操作用了1026M空间。那么该如何优化呢?
既然存在排序行为,那么是否可以考虑在排序列建索引呢?索引存储了已排序好的非空列值,那么是否可以通过建索引的方式避免排序操作呢?

检查该表发现starttime列已经存在索引。
那么为什么不走索引呢?难道一定要有限制条件?还是说空值限制了索引的使用? starttime 列确实可为空。
针对空值有两种处理办法:
1. 修改表的列 starttime 属性非空,但生产库岂敢随意修改。
alter table xxx modify starttime not null;
2. Where 条件中添加限制,只取非空值,如下:
          where 1 = 1
and wi.starttime is not null
          order by wi.starttime desc) tmp_tb
查看新的执行计划:

 PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 793409466 ----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10 | 116K| 12 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID | SYS_CODE | 1 | 17 | 2 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | SYS_C005980 | 1 | | 1 (0)| 00:00:01 |
| 3 | TABLE ACCESS BY INDEX ROWID | SYS_CODE | 1 | 17 | 2 (0)| 00:00:01 |
|* 4 | INDEX UNIQUE SCAN | SYS_C005980 | 1 | | 1 (0)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID | SYS_CODE | 1 | 17 | 2 (0)| 00:00:01 |
|* 6 | INDEX UNIQUE SCAN | SYS_C005980 | 1 | | 1 (0)| 00:00:01 |
| 7 | TABLE ACCESS BY INDEX ROWID | SYS_CODE | 1 | 17 | 2 (0)| 00:00:01 |
|* 8 | INDEX UNIQUE SCAN | SYS_C005980 | 1 | | 1 (0)| 00:00:01 |
| 9 | TABLE ACCESS BY INDEX ROWID | SYS_CODE | 1 | 17 | 2 (0)| 00:00:01 |
|* 10 | INDEX UNIQUE SCAN | SYS_C005980 | 1 | | 1 (0)| 00:00:01 |
| 11 | TABLE ACCESS BY INDEX ROWID | SYS_CODE | 1 | 17 | 2 (0)| 00:00:01 |
|* 12 | INDEX UNIQUE SCAN | SYS_C005980 | 1 | | 1 (0)| 00:00:01 |
| 13 | TABLE ACCESS BY INDEX ROWID | SYS_FUNCTION | 1 | 15 | 1 (0)| 00:00:01 |
|* 14 | INDEX UNIQUE SCAN | SYS_FUNC_ID | 1 | | 0 (0)| 00:00:01 |
| 15 | TABLE ACCESS BY INDEX ROWID | SYS_FUNCTION | 1 | 15 | 1 (0)| 00:00:01 |
|* 16 | INDEX UNIQUE SCAN | SYS_FUNC_ID | 1 | | 0 (0)| 00:00:01 |
| 17 | TABLE ACCESS BY INDEX ROWID | SYS_STRU | 1 | 21 | 2 (0)| 00:00:01 |
|* 18 | INDEX UNIQUE SCAN | STRU_ID_PK | 1 | | 1 (0)| 00:00:01 |
| 19 | TABLE ACCESS BY INDEX ROWID | SYS_STRU | 1 | 21 | 2 (0)| 00:00:01 |
|* 20 | INDEX UNIQUE SCAN | STRU_ID_PK | 1 | | 1 (0)| 00:00:01 |
| 21 | TABLE ACCESS BY INDEX ROWID | SYS_STRU | 1 | 21 | 2 (0)| 00:00:01 |
|* 22 | INDEX UNIQUE SCAN | STRU_ID_PK | 1 | | 1 (0)| 00:00:01 |
| 23 | TABLE ACCESS BY INDEX ROWID | SYS_STRU | 1 | 21 | 2 (0)| 00:00:01 |
|* 24 | INDEX UNIQUE SCAN | STRU_ID_PK | 1 | | 1 (0)| 00:00:01 |
| 25 | TABLE ACCESS BY INDEX ROWID | SYS_STRU | 1 | 21 | 2 (0)| 00:00:01 |
|* 26 | INDEX UNIQUE SCAN | STRU_ID_PK | 1 | | 1 (0)| 00:00:01 |
| 27 | SORT AGGREGATE | | 1 | 2 | | |
|* 28 | INDEX RANGE SCAN | IDX_WPINFO_RELATIONWPID | 32 | 64 | 1 (0)| 00:00:01 |
| 29 | SORT AGGREGATE | | 1 | 15 | | |
|* 30 | INDEX RANGE SCAN | IDX_WEWI_WPID | 1 | 15 | 1 (0)| 00:00:01 |
|* 31 | VIEW | | 10 | 116K| 12 (0)| 00:00:01 |
|* 32 | COUNT STOPKEY | | | | | |
| 33 | VIEW | | 10 | 116K| 12 (0)| 00:00:01 |
| 34 | TABLE ACCESS BY INDEX ROWID| WP_INFO | 1051K| 778M| 12 (0)| 00:00:01 |
|* 35 | INDEX FULL SCAN DESCENDING| IDX_WPINFO_STIME | 10 | | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id):
--------------------------------------------------- 2 - access("C"."AUTO_ID"=TO_NUMBER(:B1))
4 - access("C"."AUTO_ID"=TO_NUMBER(:B1))
6 - access("C"."AUTO_ID"=TO_NUMBER(:B1))
8 - access("C"."AUTO_ID"=TO_NUMBER(:B1))
10 - access("C"."AUTO_ID"=TO_NUMBER(:B1))
12 - access("C"."AUTO_ID"=TO_NUMBER(:B1))
14 - access("SF"."AUTO_ID"=TO_NUMBER(:B1))
16 - access("SF"."AUTO_ID"=TO_NUMBER(:B1))
18 - access("STU"."AUTO_ID"=:B1)
20 - access("STU"."AUTO_ID"=:B1)
22 - access("STU"."AUTO_ID"=:B1)
24 - access("STU"."AUTO_ID"=:B1)
26 - access("STU"."AUTO_ID"=:B1)
28 - access("WP"."RELATION_WPID"=:B1)
30 - access("WPID"=:B1)
31 - filter("ROW_ID">0)
32 - filter(ROWNUM<=10)
35 - filter("WI"."STARTTIME" IS NOT NULL) cost 从205k 下降到了12 ,评估执行时间从41min 下降到0.01 s, 效果很好有木有。看下面执行计划走了索引全扫描,没了排序操作。 实际执行 0.06s ,从147s 下降到0.06s 效率提升了2000多倍。
要等很久的一个查询秒出了。想想就有点小激动,所以记录一下。 总结:索引只保存确定值,而 Null 值不确定所以并不被索引记录,如果根据索引排序,那么这个排序并没有Null值,排序结果对于原表来说不准确,数据库不能返回给你一个假的结果,所以不能走索引。
如果索引列根本没有空值呢?所有的值都被索引所记录? 事实是不论这个列是否有空值,但既然可以为空,那么数据库就认为可能存在空值,坚决不能走索引。
通过修改列属性为非空,或在条件中限制只取非空值,数据库就知道索引中确实包含了你需要的所有值,数据库就可以放心大胆的走索引了。
同理类似,select max/min/count(1)/count(*) 都会因为可能存在空值导致返回结果不准确而不走索引。

Null 值对索引排序的影响案例一则的更多相关文章

  1. Oracle中NULL值与索引

    NULL值是关系数据库系统布尔型(true,false,unknown)中比较特殊类型的一种值,通常称为UNKNOWN或空值,即是未知的,不确定的.由于NULL存在着无数的可能,因此NULL值也不等于 ...

  2. 网页页面NULL值对浏览器兼容性的影响

    网页页面NULL值对浏览器兼容性的影响       近期做项目中一个页面中的input radio出现浏览器兼容性问题. 主要问题: 在谷歌浏览器,360急速模式和搜狗急速模式中给radio初始动态赋 ...

  3. PostgreSQL 数据库NULL值的默认排序行为与查询、索引定义规范 - nulls first\last, asc\desc

    背景 在数据库中NULL值是指UNKNOWN的值,不存储任何值,在排序时,它排在有值的行前面还是后面通过语法来指定. 例如 -- 表示null排在有值行的前面 select * from tbl or ...

  4. mysq对存在null值的字段排序

    1.建立学生表,建表sql如下: ),age int); 2.插入几条数据,包括id字段值为null的 ,),(,),(,),(),(); 3.我们查询下,可以看到存在id字段为空的值: 4.对学生表 ...

  5. 让索引包含null值的两种方法

    1. 把有NULL值的列与一个常数,或者一个带有not null约束的列一同索引 create index ind_01 on t01(col01,1); 或者 create index ind_01 ...

  6. 【mysql】mysql null值

    在数据表我们有时候有些表字段会为null,表示空.其实在mysql中null值是占用空间的. mysql手册如下解释 NULL columns require additional space in ...

  7. oracle 关于null值排序

    在oracle中根据字段来desc排序的话null值可能会在数据的最前面.然而有时候我们查看数据的时候并不希望能够在前面看到这些null值的排序数据. 因此我查了一下: 1.排序的时候运用nvl(). ...

  8. 关于null值的排序

    关于空值null的排序问题   Oracle排序中NULL值处理的五种常用方法: 1.缺省Oracle在Order by 时缺省认为null是最大值,所以如果是ASC升序则排在最后,DESC降序则排在 ...

  9. 使用复合索引代替单键索引,来避免单键有null值的情况

    查看原表: SQL> select count(*) from t1; COUNT(*) ---------- 3229088 SQL> select count(*) from t1 w ...

随机推荐

  1. linux cut: invalid byte, character or field list Try 'cut --help' for more information.

    1. 概述 centos执行简单shell 脚本 报错 cut: invalid byte, character or field listTry 'cut --help' for more info ...

  2. webstorm添加自定义代码块

    widnow下使用alt+ctrl+s 调出setting面板 mac下使用command+,(逗号)调出Preferences面板 搜索live template选中js,在javascrpt 模板 ...

  3. UFW Essentials: Common Firewall Rules and Commands

    Introduction UFW is a firewall configuration tool for iptables that is included with Ubuntu by defau ...

  4. 安装Chrome driver/ IE driver

    2014-08-15 11:38 22100人阅读 评论(0) 收藏 举报  分类: python基础学习(97)  >>>安装Chrome driver chrome driver ...

  5. myeclipse 下载 checkstyle 引入后不显示问题

    参照这篇博客,http://blog.csdn.net/zzq900503/article/details/42003499 下载最新的checkstyle版本后,在本地导入后一直不显示,步骤什么的也 ...

  6. Android Studio最新稳定版下载 - 百度网盘(更新于2017年7月14日)

    Android Studio是一个为Android平台开发程序的集成开发环境,其包含用于构建Android应用所需的所有工具.Android Studio 2.3.3为最新稳定版(截止到2017年7月 ...

  7. javascript面向对象的写法03

    javascript面向对象的写法03 js一些基础知识的说明 prototype 首先每个js函数(类)都有一个prototype的属性,函数是类.注意类有prototype,而普通对象没有. js ...

  8. Python文件夹与文件的操作 ZZ

    最近在写的程序频繁地与文件操作打交道,这块比较弱,还好在百度上找到一篇不错的文章,这是原文传送门,我对原文稍做了些改动. 有关文件夹与文件的查找,删除等功能 在 os 模块中实现.使用时需先导入这个模 ...

  9. What’s the difference between a stack and a heap?

    http://www.programmerinterview.com/index.php/data-structures/difference-between-stack-and-heap/ The ...

  10. linux中无法使用sudo的方法

    xxx is not in the sudoers file.This incident will be reported.的解决方法 1.切换到root用户下. 2.添加sudo文件的写权限,命令是 ...