正文
(3)如果只是前通配,可以使用reverse函数索引(不是翻转键索引)
原始语句:
SELECT * FROM t WHERE t.NAME LIKE '%ORADB1';
创建reverse函数索引,并改写语句,
注意查找值要倒序:
注意:
如果通配查询的是中文,要注意使用REVERSE翻转条件值,因为REVERSE内部会按字节翻转的,正确写法如:
SELECT * FROM t WHERE REVERSE(t.name) LIKE REVERSE('数据')||'%';
否则查询出来的数据不对,将可能影响到业务的正常运行。
索引列使用了函数、数学运算、其他表达式等,走不了索引
解决方法:去掉对索引列的相关运算,保持索引列纯净。
目前优化器对一些数学运算,还无法做很好的消除动作,所以对于索引列应该尽量保持纯净,否则可能无法用上正确的索引。
举例:
把语句的条件改写一下,将运算去掉:
以上例子只是简单的数学运算,可能的运算还有和其他列运算,比如where ID+ext_col...
记住一个原则:尽量保持索引列纯净。
解决方法:
必须避免隐式类型转换,全部要求显式类型转换(非索引列),且避免对索引列进行类型转换(有函数索引除外)。如果类型不一致,不管是否发生自动类型转换,谓词的右值应该显式转换为与索引列保持一致(对于非索引列的运算也应该如此)。
举例:
从以上两次查询对比来看,第一次查询发生了类型转换,可以通过执行计划中的谓词信息获知。通过分析发现,X因为是VARCHAR2,优先级比数值类型低,遇到数值类型,会TO_NUMBER隐式转换,所以索引失效。第二次查询,通过传入与索引列类型一致的字符串后,得以解决。
查询转换是非常复杂的过程,ORACLE CBO的查询转换有好几十种,比如CVM :complex view merging ,SU:subquery unnest, JPPD:JOIN PREDICATE PUSH DOWN等(在10053文件里都可以看到)。如果查询转换失败,那么必将影响后续优化器的一些操作,比如JPPD中JOIN谓词无法推入到视图中,那么很可能视图就无法走索引了。而且,查询转换有很多BUG,触发BUG需要找到原因,比如设置隐含参数、fix control等,或者改写SQL绕过BUG。如下例所示:
其中AB_XRTOFFREC_201703是UNION ALL查询组成的视图,这个查询在10.2.0.4上很正常,升级到11.2.0.4后执行计划显示不走索引,性能非常差。
在10g中的执行计划:
在11g中的错误执行计划:
通过收集统计信息都无效,将优化器降级到10.2.0.4即有效。很显然,这是引入了BUG或者新的限制。一旦遇到这种是BUG或限制导致的,可以通过10053跟踪文件或者SQLT来进行分析。对于这条语句无法走JPPD查询转换,在10053中就可以找到原因:
然后在MOS中查看得知是BUG:9380298,默认开关关闭。