1、数据库中交易流水表越来越大,对流水表以create_time列做了分区,开发配合对sql改进,加了create_time做查询条件。但是观察sql执行情况,查询sql的where条件中虽然有create_time,但是却是全表扫描所有分区,性能甚至低于分区之前
分区情况如下:
sql文本和执行计划如下:
对应的java代码如下,其中使用了timestamp类型:
2、注意到Predicate Information部分有INTERNAL_FUNCTION函数,这代表对应列是加密列或者对应列与绑定值之间做了隐式类型转换,使用了内部函数。此列非加密列,因此怀疑此列做了隐式类型转换
我们对对应sql语句使用explain plan for解释其执行计划,如下:
看到使用explain plan for看到的执行计划并没有INTERNAL_FUNCTION字样,并且Pstart和Pstop也说明走了分区消除
3、create_time列是date类型,造成隐式类型转换的原因可能是绑定值使用了其他类型,例如上面的timestamp类型,现在使用date类型再次测试如下:
可以看到,分区消除起作用了,java代码如下:
4、sql文本没有任何变化,只是代码中变量类型有所变化,影响sql执行计划
5、此问题但从数据库看不出问题所在,数据字典里显示sql使用绑定变量,并且从数据库各个方面均可分区消除,但是应用的实际sql没有分区消除,此时明白INTERNAL_FUNCTION代表的含义至关重要,了解程序代码也有所帮助
因此sql的书写一定要注意前后台数据类型一致,此处是不能分区消除,也有可能造成索引未使用等问题,影响性能