工作中遇到一种情况,使用plsql查看sql的执行计划,是使用了想要用的索引,但是程序执行的时候由于数据量过大,出现查询卡住迟迟查不出来,通过堆栈确定了确实是卡在了查询那一行,但是从sql上,以及执行计划上都没有看出问题,一时陷入僵局,不知道怎么回事,通过咨询得知,jdbc使用预编译的sql,有可能会出现索引无法使用的问题,但sql已经是最简,无法修改,最后采用了hint解决
原sql,其中gmt_modified和id字段都建立了索引,通过plsql也查看了执行计划,两个索引都有使用,以为没有问题,在测试库也正常执行(因为数据量小),但线上就直接卡住不动了(数据量是亿级别的)
select * from (
select * from test t
where t.GMT_MODIFIED >= to_date('2019-01-13 17:31:00' ,'yyyy-mm-dd hh24:mi:ss')
and t.GMT_MODIFIED < to_date('2019-01-15 17:31:00' ,'yyyy-mm-dd hh24:mi:ss')
and t.id > 0
ORDER BY t.id
)z where rownum <= 500
综合各种情况,期望的是走MGMT_IND这个索引,所以加上hint /+INDEX(t MGMT_IND)/ 指定走MGMT_IND这个索引,问题解决
select * from (
select /*+INDEX(t MGMT_IND)*/ * from test t
where t.GMT_MODIFIED >= to_date('2019-01-13 17:31:00' ,'yyyy-mm-dd hh24:mi:ss')
and t.GMT_MODIFIED < to_date('2019-01-15 17:31:00' ,'yyyy-mm-dd hh24:mi:ss')
and t.id > 0
ORDER BY t.id
)z where rownum <= 500
hint这个是在sql的执行不是期望的结果,并且sql也不能再修改的情况下来指定sql执行的一些操作,改变执行过程,但是这个不总是有用的,应该尽量少使用,可能随着数据库版本变化,业务变化,这个hint会失效