当前位置:  数据库>oracle

Oracle exists子查询出现rownum引起性能问题的优化

    来源: 互联网  发布时间:2017-06-25

    本文导语: 生产环境中有一支SQL消耗cpu资源很大,逻辑读为299361,相关问题描述: RationaleThe SQL spent 100% of its database time on CPU, I/O and Cluster waits.This part of database time may be improved by the SQL Tuning Advisor.RationaleDatabase time for this SQL was divided as follows: ...

生产环境中有一支SQL消耗cpu资源很大,逻辑读为299361,相关问题描述:

Rationale
The SQL spent 100% of its database time on CPU, I/O and Cluster waits.
This part of database time may be improved by the SQL Tuning Advisor.
Rationale
Database time for this SQL was divided as follows: 100% for SQL
execution, 0% for parsing, 0% for PL/SQL execution and 0% for Java
execution.
Rationale
SQL statement with SQL_ID "7ptu1y0d95s2r" was executed 3209 times and
had an average elapsed time of 20 seconds.
原SQL:
update WWH
set WWH.STATUS = (case
when (select count(1)
from WWD
where

.........................

and exists (select 1
from WWD
where 1 = 1
and WWH.WH = WWD.WH
and WWH.WAVE = WWD.WAVE
and WWD.SO in ('2349212263452' )
and rownum = 1)


set line 1000
set pagesize 1000
set timing on
set autotrace traceonly
执行SQL.........

查看执行计划如下:

Execution Plan
----------------------------------------------------------
Plan hash value: 3044987130

--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 1 | 45 | 191K (1)| 00:38:18 |
| 1 | UPDATE | WWH | | | | |
|* 2 | FILTER | | | | | |
|* 3 | TABLE ACCESS FULL | WWH | 98070 | 4309K| 449 (1)| 00:00:06 |
|* 4 | COUNT STOPKEY | | | | | |
|* 5 | INDEX UNIQUE SCAN | UNQ_WWD | 1 | 40 | 2 (0)| 00:00:01 |
| 6 | SORT AGGREGATE | | 1 | 24 | | |
|* 7 | COUNT STOPKEY | | | | | |
|* 8 | FILTER | | | | | |
|* 9 | INDEX RANGE SCAN | UNQ_WWD| 1 | 24 | 3 (0)| 00:00:01 |
| 10 | SORT AGGREGATE | | 1 | 27 | | |
|* 11 | TABLE ACCESS BY INDEX ROWID| WWD | 1 | 27 | 4 (0)| 00:00:01 |
|* 12 | INDEX RANGE SCAN | UNQ_WWD| 1 | | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - filter( EXISTS (SELECT 0 FROM "WWD" WHERE ROWNUM=1 AND
"WWD"."WH"=:B1 AND "WWD"."SO"='2349212263452' AND "WWD"."WAVE"=:B2))
-............................................

.............................................

Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
263080 consistent gets
0 physical reads
72 redo size
829 bytes sent via SQL*Net to client
3583 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
0 rows processed
上面显示表没走索引,逻辑读为263080,查看表的字段(WAVE,WH)存在索引,我们再建一个选择性更好的索引:
增加索引:
create index IND_MODIFY_TIME_IX on WWH(Modify_Time,WAVE,WH) tablespace wsx;

再查看执行计划依然没有走索引,逻辑读同样是263080大。

强制加入索引后,虽然执行计划中有显示走了全索引扫描,且驱动表由WWH表变成了WWD表,但逻辑读变得更大为299361,走索引前后性能都差的最主要原因是执行计划中看到有
"filter( EXISTS..........."这行,表示子查询没有展开。
SQL> update /*+index(WWH IND_MODIFY_TIME_IX) */ WWH ................

Elapsed: 00:00:01.11

Execution Plan
----------------------------------------------------------
Plan hash value: 389457693

----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 1 | 45 | 196K (1)| 00:39:16 |
| 1 | UPDATE | WWH | | | | |
|* 2 | TABLE ACCESS BY INDEX ROWID | WWD | 4903 | 215K| 5302 (1)| 00:01:04 |
|* 3 | INDEX FULL SCAN | IND_MODIFY_TIME_IX | 4996 | | 602 (1)| 00:00:08 |
|* 4 | COUNT STOPKEY | | | | | |
|* 5 | INDEX UNIQUE SCAN | UNQ_WWD | 1 | 40 | 2 (0)| 00:00:01 |
| 6 | SORT AGGREGATE | | 1 | 24 | | |
|* 7 | COUNT STOPKEY | | | | | |
|* 8 | FILTER | | | | | |
|* 9 | INDEX RANGE SCAN | UNQ_WWD | 1 | 24 | 3 (0)| 00:00:01 |
| 10 | SORT AGGREGATE | | 1 | 27 | | |
|* 11 | TABLE ACCESS BY INDEX ROWID| WWD | 1 | 27 | 4 (0)| 00:00:01 |
|* 12 | INDEX RANGE SCAN | UNQ_WWD | 1 | | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - filter( EXISTS (SELECT 0 FROM "WWD" WHERE ROWNUM=1 AND
"WWD"."WH"=:B1 AND "WWD"."SO"='2349212263452' AND "WWD"."WAVE"=:B2))
-............................................

.............................................


Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
299361 consistent gets
2 physical reads
0 redo size
840 bytes sent via SQL*Net to client
3619 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
2 sorts (memory)
0 sorts (disk)
0 rows processed

手工加入/*+unnest*/让子查询展开,但从执行计划查看,依然没有展开。

exists无法展开子查询,我们将SQL等价改成in子查询,如下:

SQL略

 

Execution Plan
----------------------------------------------------------
Plan hash value: 1922347980

--------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 1 | 81 | 616 (1)| 00:00:08 |
| 1 | UPDATE | WWH | | | | |
| 2 | NESTED LOOPS | | 1 | 81 | 607 (1)| 00:00:08 |
| 3 | NESTED LOOPS | | 1 | 81 | 607 (1)| 00:00:08 |
| 4 | VIEW | VW_NSO_1 | 1 | 36 | 4 (0)| 00:00:01 |
| 5 | SORT UNIQUE | | 1 | 40 | | |
|* 6 | COUNT STOPKEY | | | | | |
| 7 | TABLE ACCESS BY INDEX ROWID| WWD | 1 | 40 | 4 (0)| 00:00:01 |
|* 8 | INDEX RANGE SCAN | UNQ_WWD | 1 | | 3 (0)| 00:00:01 |
|* 9 | INDEX FULL SCAN | IND_MODIFY_TIME_IX | 1 | | 601 (1)| 00:00:08 |
|* 10 | TABLE ACCESS BY INDEX ROWID | WWH | 1 | 45 | 602 (1)| 00:00:08 |
| 11 | SORT AGGREGATE | | 1 | 24 | | |
|* 12 | COUNT STOPKEY | | | | | |
|* 13 | FILTER | | | | | |
|* 14 | INDEX RANGE SCAN | UNQ_WWD | 1 | 24 | 3 (0)| 00:00:01 |
| 15 | SORT AGGREGATE | | 1 | 27 | | |
|* 16 | TABLE ACCESS BY INDEX ROWID | WWD | 1 | 27 | 4 (0)| 00:00:01 |
|* 17 | INDEX RANGE SCAN | UNQ_WWD | 1 | | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

此部分看不到exists和filter信息了,说明有展开


Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
3 consistent gets
2 physical reads
0 redo size
842 bytes sent via SQL*Net to client
3546 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
3 sorts (memory)
0 sorts (disk)
0 rows processed
发现上面已走索引了,且逻辑读降为3。

以上是在测试环境中模拟测试,因数据与正式环境有差异,我们再看下正式环境中查询操作性能比较:

select count(*) from WWH
where exists (select 1
from WWD
where 1 = 1
and WWH.WH= WWD.WH
and WWH.WAVE= WWD.WAVE
and WWD.SO in ('SO201612345' )
and rownum = 1
)
and WWH.STATUS '11'
and WWH.STATUS '22'

---逻辑读625043,执行时间为1秒

改成in子查询后:

SELECT COUNT ( * )
FROM  WWH
WHERE (wwh.WH, wwh.WAVE) IN
(SELECT WWD.WH, WWD.WAVE
FROM  WWD
WHERE 1 = 1
AND WWD.SO_NO IN ('SO201612345')
AND ROWNUM = 1
)
AND WWH.STATUS '11'

and WWH.STATUS '22'

---逻辑读变为8,执行时间58豪秒。

也可直接去掉rownum=1。
总结:当exists子查询中出现有rownum时,子查询无法展开,可以改成in子查询或表联接,或根据实际逻辑需求,去掉rownum。


    
 
 

您可能感兴趣的文章:

  • Linux(Oracle系统在上面)系统无缘无故死机 , 可能是由于应用程序引起 , 可是由于重新启动查不到相关信息 , 不知道在哪里有记录系统CPU Lo
  • Oracle外键不加索引引起死锁示例
  • 一次误操作引起的Oracle数据库大恢复
  • Oracle 数据库(oracle Database)性能调优技术详解
  • Oracle收购TimesTen 提高数据库软件性能
  • 关于提高Oracle数据库性能的四个错误认识
  • 用Oracle动态性能视图采集查询调优数
  • Oracle性能究极优化 上第1/2页
  • 用PHP连mysql比oracle数据库性能好
  • Oracle性能究极优化 下
  • 保持Oracle数据优良性能的技巧分享
  • 100分寻求最优化的连接oracle的java程序,请给我讲出理由,我是初学者,在做项目时不想让连接oracle影响我的程序性能
  • Oracle数据库应用程序性能优化探究
  • oracle 使用递归的性能提示测试对比
  • 善用Oracle表空间设计提升数据库性能
  • Oracle性能究极优化
  • Oracle SQL性能优化系列学习一
  • Oracle SQL性能优化系列学习三
  • Linux平台下如何监控Oracle数据库的性能
  • Oracle SQL性能优化系列学习二
  • 性能陷阱:Oracle表连接中范围比较
  • 基于Oracle的高性能动态SQL程序开发
  • 浅谈Oracle性能优化可能出现的问题
  • 如何保持Oracle数据库的优良性能
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • linux下安装oracle,出现没有权限的报警,怎么解决?
  • 我在安装oracle的时候出现了这个错误,请懂行人赐教~~附图!~~
  • solaris下安装oracle出现的异常
  • linux下安装oracle出现bash:sqlplus:command not found
  • linux iis7站长之家
  • oracle远程连接服务器出现 ORA-12170 TNS:连接超时 解决办法
  • Oracle数据库运行Oracle form时避免出现提示信息
  • 请高手帮帮我!oracle安装完出现了点问题!着急中!!
  • 在Red Hat 上安装Oracle 9i 出现的问题
  • oracle9i安装出现的一个问题!
  • 安装oracle出现error:ora-01031:insufficient privilleges的解决
  • linux下安装oracle8.1.7出现的问题
  • Linux上管理本机Oracle的时候出现找不到ServiceName的错误
  • 为什么在编译java程序的时候出现oracle.jdbc.driver不存在?急!!!
  • Oracle除去数据中的换行符以免读取出现问题
  • 【求助】RHEL5.1 下安装Oracle 10.2g出现问题:指定数据库方案口令后卡住了,不能安装
  • 关于SHELL调用oracle存储过程出现的一个小问题
  • 在tomcat下连接oracle8i的javabean出现如下错误,急!
  • secureCRT远程连接服务器操作oracle数据库出现的问题
  • Oracle10g EM出现乱码的解决方法
  • Oracle 12c发布简单介绍及官方下载地址
  • 在linux下安装oracle,如何设置让oracle自动启动!也就是让oracle那个服务自动启动,不是手动的
  • oracle 11g最新版官方下载地址
  • 请问su oracle 和su - oracle有什么不同?
  • Oracle 数据库(oracle Database)Select 多表关联查询方式
  • 虚拟机装Oracle R12与Oracle10g
  • Oracle数据库(Oracle Database)体系结构及基本组成介绍
  • Oracle 数据库开发工具 Oracle SQL Developer
  • 如何设置让Oracle SQL Developer显示的时间包含时分秒
  • Oracle EBS R12 支持 Oracle Database 11g
  • Oracle 10g和Oracle 11g网格技术介绍


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3