同样的sql传入的条件不同执行效率相差百倍的原因

这个是公司另一个项目组遇到的事情,记录下

**项目有一条查询SQL是这样的:

select s.id                id ,

      s.end_user_id       endUserId,

      s.order_code        orderCode,

      s.order_create_time orderCreateTime,

      s.receive_date      receiveDate,

      s.is_leaf           isLeaf,

      s.parent_so_id      parentSoId,

      s.site_type         siteType,

      s.merchant_id       merchantId,

      s.order_Type        orderType

  from ( select rownum rn, rd

          from (select rowid rd

                  from so_data2.so si

                 where si.receive_date>= to_date(#receiveDate# 'yyyy-mm-dd' )

                   and si.receive_date< to_date(#receiveDate#  'yyyy-mm-dd' )

                   and si.is_leaf= 1

                   and si.order_status in ( 2435 )

                   and si.update_time>= to_date(#receiveDate#  'yyyy-mm-dd' )

                   and si.order_create_time>=

                      to_date( '2013-04-01 00:00:00' , 'yyyy-mm-ddhh24:mi:ss')

                   and si.order_create_time<

                      to_date(#receiveDate#  , 'yyyy-mm-dd' ))

         where rownum <= 1000) p,

      so_data2.so s

  where p.rn> 0

   and p.rd= s.rowid

 

这条SQL,只有收货时间是入参。并且有3个条件:

si.receive_date>= to_date(#receiveDate# 'yyyy-mm-dd' )

and si.receive_date< to_date(#receiveDate#  'yyyy-mm-dd' )

and si.update_time>= to_date(#receiveDate#  'yyyy-mm-dd' )

and si.order_create_time< to_date(#receiveDate#  , 'yyyy-mm-dd' ))

其中receive_date是>= 和 < 2个条件,update_time只是>=这1个条件。

 

问题描述:

在开始初始化**数据的时候,是从2013-04-01开始查数据的,每次查一天。那时候初始化数据,这个SQL执行效率大概在10S以内;

初始化数据结束之后,定时任务每天晚上查询前一天收货完成的订单,效率也都是在10S以内。

 

这次**体系的开发,也需要用这个接口来初始数据,从2013-07-01开始查询收货完成的订单。但是上STG就发现,这个接口非常慢,需要将近2、3分钟,有时候还会超时。但是就是在会员体系调这个接口超时的情况下,凌晨查询前一天订单的定时任务调这个接口,还是稳定在10s左右。同一个SQL,只是参数不同,为什么差别会这么大呢?并且之前**初始化数据的时候,也是查几个月前的数据,为什么那时候初始化效率也很高呢?

 

定位过程:

Step1:首先怀疑BI数据库是否做了历史数据归档等操作,才导致查前一天的很快,但是查7月份数据很慢。通过咨询BI同事,他们数据库并没有做什么归档,都是按照时间分区的,并没有什么变化。

 

Step2:把SQL发给BI同事,他们在PL/SQL客户端执行这条sql,时间就填成7月的某一天,也是在几秒内就返回了,并不会存在效率问题。

最后,找到DBA**,让我们在SQL里加上/*+ louis */,加完之后效果马上显现了,这个SQL又从2分多钟,恢复到了几秒。鉴证奇迹的时候到了。当时都不明白这是什么情况,把代码回滚又测了一次,结果执行时间还是2分多钟,再把这个神奇的/*+ louis */加上,立马又恢复到了几秒以内。

 

Step3:咨询了下DBA,这个/*+ louis */是什么意思,刚开始,他让我们加这个的意思是加个标记,到时候好分析这个SQL执行时的执行计划,没想到加了之后,问题立马就解决了。百度一下,才知道这个是orcale的机制--HINT。之所以加了/*+ louis */效率会提升,是因为指定的这种机制louis(其实,这个是DBA的英文名),不存在,所以查询优化器会重新解析这条SQL,重新根据绑定的参数制定执行计划,所以又可以用到receive_date字段的索引了。

 

最后,百度了一下,大概得出了如下的分析结论:

1、查4月份数据,数据查询优化器会走receive_date这个索引,因为update_time这个数据非常大。所以,当时初始化数据的时候,效率也是很高,查询SQL大概在秒级;

2、现在初始化数据跑完了,每天查前一天的数据,这个时候,数据库自动优化成了走update_time的索引。

3、当这时候再次执行这条SQL,传的日期是7月1号,由于是通过绑定变量的方式,执行计划没有改变,还是走的update_time这个索引,而日期是7月1号,并且条件里只有update_time >= ,没有小于,这时候用update_time的索引,效率就非常低了。

4、采用hint方式,指定走receive_date索引,在SQL中第一行改成:select /*+ INDEX(SIIDX_YHD_SO_RECEIVE_DATE) */ s.id id, 

 ,传入7月1号,执行时间从之前的200S+,降低到了2S左右,效率提升了100+倍了

 

结合之前fraudpool有条SQL,在PL/SQL执行和代码调用耗时查表非常大,也是因为是代码通过绑定变量的方式,导致数据库采用了之前解析过的执行计划,从而没有走到理想的索引。类似这里问题,以后大家都可以通过HINT这种方式尝尝试优化一下,效果,呵呵,谁用谁知道。

 

关于HINT的用法和疗效,大家可以自己百度一下,这里就不贴文档了。如果有兴趣,可以去了解一下,相信有帮助。

已标记关键词 清除标记
相关推荐
【为什么还需要学习C++?】 你是否接触很多语言,但从来没有了解过编程语言的本质? 你是否想成为一名资深开发人员,想开发别人做不了的高性能程序? 你是否经常想要窥探大型企业级开发工程的思路,但苦于没有基础只能望洋兴叹?   那么C++就是你个人能力提升,职业之路进阶的不二之选。 【课程特色】 1.课程共19大章节,239课时内容,涵盖数据结构、函数、类、指针、标准库全部知识体系。 2.带你从知识与思想的层面从0构建C++知识框架,分析大型项目实践思路,为你打下坚实的基础。 3.李宁老师结合4大国外顶级C++著作的精华为大家推出的《征服C++11》课程。 【学完后我将达到什么水平?】 1.对C++的各个知识能够熟练配置、开发、部署; 2.吊打一切关于C++的笔试面试题; 3.面向物联网的“嵌入式”和面向大型化的“分布式”开发,掌握职业钥匙,把握行业先机。 【面向人群】 1.希望一站式快速入门的C++初学者; 2.希望快速学习 C++、掌握编程要义、修炼内功的开发者; 3.有志于挑战更高级的开发项目,成为资深开发的工程师。 【课程设计】 本课程包含3大模块 基础篇 本篇主要讲解c++的基础概念,包含数据类型、运算符等基本语法,数组、指针、字符串等基本词法,循环、函数、类等基本句法等。 进阶篇 本篇主要讲解编程中常用的一些技能,包含类的高级技术、类的继承、编译链接和命名空间等。 提升篇: 本篇可以帮助学员更加高效的进行c++开发,其中包含类型转换、文件操作、异常处理、代码重用等内容。
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页