--原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. 数组之reduce()和reduceRight()

    1.reduce()和reduceRight()方法使用指定的函数将数组元素进行组合,生成单个值. reduce()可以传入两个参数,第一个是执行化简操作的函数.同样这个函数可以有参数,第一个参数代表 ...

  2. 前端学习之路之CSS (三)

    Infi-chu: http://www.cnblogs.com/Infi-chu/ 创建CSS有三种方法:外部样式表.内部样式表.内联样式.优先级:内联样式>内部样式>外部样式表> ...

  3. 11.6NOIP模拟赛解题报告

    心路历程 预计得分:\(100 + 100 + 100 = 300\) 实际得分:\(100 +100 +100 = 300\) 学OI两年终于AK了一次qwq(虽然题目炒鸡水..) 纪念一下这令人激 ...

  4. ideal key

    常用快捷键 设置快捷键:File -> Settings -> IDE Settings -> Keymap -> 选择“eclipse” -> 然后“Copy”一份 - ...

  5. 003客户端负载均衡Ribbon & 短路器Hystrix

    1.POM配置 和普通Spring Boot工程相比,仅仅添加了Eureka.Ribbon.Hystrix依赖和Spring Cloud依赖管理 <dependencies> <!- ...

  6. git使用笔记 bitbucket基本操作

    实现目标: 1.将本地已经存在的项目文件保存到 bitbucket.org 2.从 bitbucket.org 检出代码库到本地 操作笔记: 1.首先在bitbucket.org创建一个代码库,并得到 ...

  7. libgdx for eclipse开发环境搭建

    1.安装jdk1.7以上 2.下载libgdx1.2.0 下载地址:https://libgdx.badlogicgames.com/releases 3.下载项目创建工具(老版本的) 下载地址:ht ...

  8. LESS嵌套中的Mixins和classes

    less的嵌套规则对于有效组织你的css代码有较好的作用.其中使用mixin或者class都可以作为被嵌套的实体,但是二者还是有区别的: mixin必须由.name+(){}的pattern来定义,而 ...

  9. Virtualenv-windows

    1.下载 pip3 install virtualenv 2.创建虚拟化环境 3. 进入虚拟化目录 4.推出虚拟化环境 5.指定python版本 二.virtualenvwrapper的使用 1.下载 ...

  10. 获取所有权windows目录所有权

    Takeown /r /f 盘符:\目录\目录 例如: Takeown /r /f C:\Windows\CSC