最近线上遇到一个慢sql的问题。在QA环境时,数据量不是特别大,测试时没有发现sql性能问题。到了生产环境的时候,由于表里面有上千万的数据,导致查询sql执行时间都大于10s。查询到的数据其实并不多就是几百条。找了整整一天,最后才找到问题。
首先我们看一下这个sql
SELECT * FROM TBL_PAYMERNT_ORDER WHERE CREATE_TIME >? AND CREATE_TIME ‘2017-09-11 00:00:00’ AND CREATE_TIME
这个现象就让我觉得奇怪了。当然我们的查询是用到了公司统计一查询组件。当时一直以为是查询组件有问题。但是同样的查询组件我们在其他地方使用都没有发现类似的问题。后来仔细分析,发现第一个sql和第二个sql是有区别的。第一个sql,使用了最常用的preparedstatement 方式,应该说是不会出问题的。最后分析了一下我们查询组件在进行set paremter 时, 会根据值的class类型来设置值。我们前端传递过来的时候String类型的。这就导致了我们对timestamp 类型的字段使用了setString 方式进行赋值。这样导致了这个sql不走索引了。当我将这个字段的类型改为timestamp类型时,执行速度就和我的第二个sql一样,证明此时确实走了索引了。对于第一种用法,DB2在执行时内部隐式地对CREATE_TIME使用了转换函数,所以导致了sql执行时索引失效。而第二种方式不会使用到转换函数从而可以走索引。让我们回忆一下数据库索引优化中,是不是说明了如果对一个索引字段使用了函数将不再走索引。有些时候我们没有使用和数据库字段本身类型相对应的类型可能会导致数据库对该字段使用内部函数进行转换,这样会导致我们sql的索引失效。平时开发过程中要特别注意,虽然我们已经将功能实现了,但是性能需求也是需要重视的。
领取专属 10元无门槛券
私享最新 技术干货