这是一个非常典型的索引优化案例,我在2021年06月15日培训 中的故事篇里面提到过, 一个SQL占了一个exadata高级硬件环境的绝大部分资源, 平均执行时间51秒. 今天我再详细分析一下这个案例.
下面截取的是AWR按执行时间排名的top SQL:
下面截取的是分别按CPU,磁盘读,逻辑读排名的Top SQL,:
从上面的截图可见, 该系统的一个Top SQL消耗的一多半的系统资源.
SQL比较简单, 就是一个单表查询, 表不算太大, 370多万记录, 占用空间13G,一个贷款业务, 历史数据不能清理.
用户也尝试建了一个3字段索引, 但是用不上, 执行计划还是全表扫描. sql_text及索引如下:
SELECT *
FROM CUSTOM_APPLY_xxx
WHERE (
(TO_DATE(:1 , 'YYYYMMDDHH24MISS') >= TO_DATE(CREATE_TIME, 'YYYYMMDDHH24MISS')
AND PUSH_CREDIT_FLAG = 'I')
OR
(PUSH_CREDIT_FLAG = 'F' AND PUSH_CREDIT_COUNT > 3)
)
AND (CREDIT_REPORT_TYPE = '1' or CREDIT_REPORT_TYPE is null);
--创建的索引如下:
CREATE INDEX "IDX_CUSTOM_APPLY_xxx" ON "CUSTOM_APPLY_xxx"
("CREATE_TIME", "PUSH_CREDIT_COUNT", "PUSH_CREDIT_FLAG");
看到这里, 不知道各位读者有什么优化思路?
有优化经验的人可能一眼就看到了一个问题: create_time字段上使用了to_date函数, 导致索引失效.
TO_DATE(:1 , 'YYYYMMDDHH24MISS') >= TO_DATE(CREATE_TIME, 'YYYYMMDDHH24MISS') 这个写法确实不够规范, 也是我在给很多的开发人员培训时多次强调的.
把create_time字段上的to_date函数去掉,或者改成to_date函数索引就行了吗?