SQL优化案例1

SQL语句(0kym2mpab9k16):

SELECT COUNT(*)
  FROM TF_BH_TRADE_CBSS A
 WHERE A.TRADE_TYPE_CODE IN ('141', '142')
   AND A.USER_ID = :B2
   AND A.ACCEPT_DATE > :B1
   AND A.SUBSCRIBE_STATE = '9'

我们从1号早上的AWR报告中看到这条语句开销非常大,初看之,这么简单的一条语句,从理论上来讲应当没什么问题,也不存在可优化的地方。仔细看一下报告,却可以发现,这条语句执行的次数并不多,才4500次,但是每次执行的gets却非常大,达到了51万。

如果我们参照语句的业务逻辑来理解一下,这个语句应当是根据user_id来进行统计,而每个user_id是应该有索引的,并且每个user_id对应的行数应该也是非常有限的。按照经验来推断,SQL执行的gets开销应该在几百以内,不应该上千,更不应该上万了。那应该是执行计划出问题了。

那接下来我们来看看执行计划:

select dbms_xplan.display_awr('0kym2mpab9k16') from dual ;


这下子比较明显了,有两个不同的执行计划,分别走了两个不同的索引,从索引的名字上也可以判断,一个走了user_id,一个走了acceptdate。那基本可以确定了,这个语句的问题就在于错用了accept_date字段上的索引,accept_date的选择性比较低,导致了大量的开销。

那如何解决呢?

1、优先应该考虑的是重新收集统计信息,相信Oracle在绝大部分情况下都是可以得出高效的执行计划的。很多这种情况是由于统计信息陈旧或者错误误导了Oracle,得到了错误的执行计划。

2、使用强制索引,然后更新重新发布代码

SELECT /*+index(a,idx_tf_bh_trade_cbss_userid) */  COUNT(*)
  FROM TF_BH_TRADE_CBSS A
 WHERE A.TRADE_TYPE_CODE IN ('141', '142')
   AND A.USER_ID = :B2
   AND A.ACCEPT_DATE > :B1
   AND A.SUBSCRIBE_STATE = '9'

3、其他方式固定执行计划。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值