Oracle入参类型不对导致索引失效

DB : oracle 11.2.0.4
OS: Linux 2.6.32-573.12.1.el6.x86_64

发现问题

新开发的项目,上线后监控发现db主机cpu负载增加一倍,由原来的10%变成20%!

zabbix cpu load.jpg

排查问题

通过v$session 抓到正在执行的sql:

SELECT SUPP_GOODS_ID, update_time FROM SUPP_GOODS WHERE :"SYS_B_0"=:"SYS_B_1"   AND update_time > :1;

有多个类似这种根据update_time条件来扫描数据的sql。
分析该表的索引发现这类表的update_time字段均没有索引,不明白为何压测能通过。
正常应该是需要走仿真环境压测,可能由于数据量原因导致问题没暴露出来。

第一反应,加上索引:

create index IDX_SUPP_GOODS_UPTIME on SUPP_GOODS (UPDATE_TIME) ;

继续观察,发现一个奇怪的现象,从数据库v$sqlarea 里抓到的sql是可以走索引的,而且找开发抓了后台日志的sql,也是ok的。但是查看ash视图,还是不走索引,于是通过cursor_id 查看真实的执行计划,如下:


真实执行计划.png

这里发现谓词那里走了 internal_function 函数,应该是发生了隐式转换,于是查看下绑定变量的值:


绑定变量.jpg

看到DATATYPE_STRING字段,差不多可以确定问题了。
UPDATE_TIME字段类型为 date,与传入参数timestamp之间发生了隐士转换,导致索引失效。

字段类型是timestamp:
>to_date() 可以走索引;
>timestamp 可以走索引;
字段类型是date:
>to_date() 可以走索引;
>timestamp 不走索引。

所以这里就是 >timestamp 不走索引的情况,让开发改下代码,把值to_date()一下再传进来,就ok了。

观察负载情况,降下来了:


cpu load.jpg

你可能感兴趣的:(Oracle入参类型不对导致索引失效)