签到成功

知道了

CNDBA社区CNDBA社区

优化一个rownum=1的sql

2017-03-22 16:00 3046 0 转载 Oracle 性能优化
作者: Expect-乐

本文已获原作者授权转载。文章出自微信公众帐号:老虎刘谈SQL优化

作者介绍:老虎刘,原oracle 研发部门 Real-World Performance TEAM 成员,现在售后部门SSC专职做数据库性能优化,主要为银行、通信、证券、制造等大型企业提供服务。


因为一直身体不适,挺长时间没写文章了,今天先写个简单的吧。


这是某个客户的BOSS系统中的一个top sql,SQL代码如下:

SELECT 

t1.seq AS sequence ,

t1.TemplateID AS templateId ,

t1.parameter AS parameter ,

t1.SERVICE_NO AS serviceNo ,

trim(t1.phone_no) AS phoneNo ,

http://www.cndba.cn/Expect-le/article/1824

to_char(t1.INSERT_TIME, 'yyyymmddhh24miss') AS insertTime ,

t1.OP_CODE AS op_code ,t1.LOGIN_NO AS login_no ,

t1.SERV_NO AS servNo ,t1.SERV_NAME AS servName ,

to_char(t1.send_time, 'yyyymmddhh24mi') AS sendTime ,

t1.SUB_PHONE_SEQ AS subPhoneNo ,t1.hold1 AS hold1 ,

t1.hold2 AS hold2 ,t1.hold3 AS hold3 ,t1.hold4 AS hold4 ,t1.hold5 AS hold5

 FROM PUSH_1_8610 t1 

WHERE rownum <= : 1;http://www.cndba.cn/Expect-le/article/1824

非常简单的一个SQL,每执行一次要消耗非常高的buffer gets,见下图:




执行计划是全表扫描:

-----------------------------------------------------------------------------------

 | Id | Operation | Name | E-Rows |E-Bytes| Cost (%CPU)| E-Time | 

----------------------------------------------------------------------------------- 

| 0 | SELECT STATEMENT | | | | 1680 (100)| |http://www.cndba.cn/Expect-le/article/1824

|* 1 | COUNT STOPKEY | | | | | | 

| 2 | TABLE ACCESS FULL| PUSH_1_8610 | 1 | 2513 | 1680 (2)| 00:00:09 |

 -----------------------------------------------------------------------------------

正常来讲,随便从一张表取一条记录,如果表的每个block都有数据,只需要读一次就可以返回了。但是,如果表的blocks数很多,但开始部分是空的(delete了),或者整张表的记录都被delete了,那么就需要把整张表都扫描完才行。

这张表就是这样的,16471个blocks,0条记录。


针对这种sql,可以借助index的hint一招搞定,但是有个要求就是,表上这个index用到的字段必须有一个定义是not null,符合这样的索引随便找一个就行。 这样就不用走全表扫描了。


这个表有个主键:PK_PUSH_1_8610,那优化后的SQL就变成了:http://www.cndba.cn/Expect-le/article/1824

http://www.cndba.cn/Expect-le/article/1824

http://www.cndba.cn/Expect-le/article/1824

SELECT /*+ index(t1 PK_PUSH_1_8610) */ 

t1.seq AS sequence ,t1.TemplateID AS templateId ,

t1.parameter AS parameter ,t1.SERVICE_NO AS serviceNo ,

http://www.cndba.cn/Expect-le/article/1824

trim(t1.phone_no) AS phoneNo ,to_char(t1.INSERT_TIME, 'yyyymmddhh24miss') AS insertTime ,

http://www.cndba.cn/Expect-le/article/1824

t1.OP_CODE AS op_code ,t1.LOGIN_NO AS login_no ,t1.SERV_NO AS servNo ,

t1.SERV_NAME AS servName ,to_char(t1.send_time, 'yyyymmddhh24mi') AS sendTime ,

t1.SUB_PHONE_SEQ AS subPhoneNo ,t1.hold1 AS hold1 ,t1.hold2 AS hold2 ,

t1.hold3 AS hold3 ,t1.hold4 AS hold4 ,t1.hold5 AS hold5 

FROM PUSH_1_8610 t1 

WHERE rownum <= : 1;

http://www.cndba.cn/Expect-le/article/1824

加了这个hint后,不管表的数据如何变化,都会在几毫秒内返回结果。


今天刚刚看到公司内一位老前辈写的一篇文章,讲到慎用hint。大方向是对的,但是,有些sql还是需要hint来进行优化,这个SQL就是个例子。


我之前的一些公众号文章也有一些SQL是需要hint来优化的。尤其在很多谓词条件复杂或者关联条件复杂的情况下,靠统计信息是没有办法对行源进行准确估值的,这个时候就必须借助hint来帮助优化器制定一个良好的执行计划。作为一个高级DBA或是开发人员,hint还是需要掌握的。http://www.cndba.cn/Expect-le/article/1824

用户评论
* 以下用户言论只代表其个人观点,不代表CNDBA社区的观点或立场
Expect-乐

Expect-乐

关注

Without the continuous bitter cold, there can be no fragrant plum blossom

  • 336
    原创
  • 6
    翻译
  • 100
    转载
  • 41
    评论
  • 访问:1378766次
  • 积分:1957
  • 等级:核心会员
  • 排名:第3名
精华文章
    最新问题
    查看更多+
    热门文章
      热门用户
      推荐用户
        Copyright © 2016 All Rights Reserved. Powered by CNDBA · 皖ICP备2022006297号-1·

        QQ交流群

        注册联系QQ