问题描述
问题描述:
看到有一个语句执行时间很长,拿出来看了看执行计划
如下:
Plan Hash Value : 3431444516
| Id | Operation | Name | Rows | Bytes | Cost | Time |
| 0 | DELETE STATEMENT | | 35771435 | 894285875 | 13427529 | 44:45:31 |
| 1 | DELETE | GJT_BALANCE | | | | |
| 2 | PARTITION RANGE ALL | | 35771435 | 894285875 | 13427529 | 44:45:31 |
| * 3 | TABLE ACCESS FULL | GJT_BALANCE | 35771435 | 894285875 | 13427529 | 44:45:31 |
Predicate Information (identified by operation id):
- 3 - filter(TO_CHAR(INTERNAL_FUNCTION(“CREATE_DATE”),‘yyyymmdd’)=TO_CHAR(SYSDATE@!,‘yyyymmdd’))
语句如下:
DELETE GJT_BALANCE
WHERE TO_CHAR(CREATE_DATE, ‘yyyymmdd’) = TO_CHAR(SYSDATE, ‘yyyymmdd’)
首先思路是:根据执行计划看operation项,发现只有一个表GJT_BALANCE ,where条件是create_date ,又看了表的对应列,有索引,但是在执行计划时,没有走索引而是走的table acces full,然后我就用hit 添加强制走索引,如下:**DELETE GJT_BALANCE
WHERE /+index(IDX_CREATE_DATE)/ TO_CHAR(CREATE_DATE, ‘yyyymmdd’) = TO_CHAR(SYSDATE, ‘yyyymmdd’) 但是执行还是没有变化,还是全表扫,有优化方面的大佬,就针对我描述的能给优化一下吗?
专家解答
每日优化一小步,此次案例是delete操作没有正确使用函数索引引发的执行时间长,效率低。
根据墨天轮笔名”始于脚下“ 大佬的提供的思路,我自己检查了数据库表的索引,先是让操作走表的索引,所以想到了hit" /+index(表名 索引名)/ " 但是效果没有变化,所以此路不通,再根据大佬思路,看看表对应的字段有没有函数索引,发现表中有对应的函数索引,此时思考为啥没有走呢?然后查了查函数索引的相关资料,可以参考:https://www.cnblogs.com/sopost/archive/2010/01/20/2190121.html 还有引用函数索引格式要跟创建的字段一致,否则不会生效,可以对比上面的语句,还有一种方式就是改造条件,WHERE CREATE_DATE = TO_CHAR(SYSDATE, ‘yyyymmdd’)去匹配create_date的时间格式,效果比上面的修改还明显,所以此次的优化,总结为,函数索引虽有,但是未使用,还有就是sql语句书写不认真导致。




