自己原文公众号: https://mp.weixin.qq.com/s/Zt2_WCCi0V0Y82NzWKx7lQ
有个人找到我说语句太慢。语句核心部分是这样的。我提炼一下。
SELECT * FROM log a WHERE a.create_time >= to_date('2018-01-01', 'yyyy-mm-dd') AND a.create_time <= to_date('2021-06-30', 'yyyy-mm-dd')。我第一反应你这个查3年必然慢。当然事情如果就这样简单,就不用写这个帖子了。因为我让他试了一下我查一年和查3年的执行计划居然是一样的。更加想不到的是查一个月和查3年也是一样的,都是全表。
看到这里大家第一反应是没索引对吗?这个我当然也想到了。我让他看了一看有的。而且看这个SQL的语法就知道是Oracle的。索引对类型也对。
那么干扰执行计划的最大可能是统计信息,我让他看了一下也是不久前收集的,应该问题不大。但是抱着奇葩的心理就奇葩来一下。这里考验的就是干不干做了?凭借经验这个压力不大因为全表数据才几千万(表不过亿在我这里都不好意思叫大表)。反馈给我果然7秒完成了。定睛一看执行计划,它居然是纹丝不动。
那么索引有问题?尽管Oracle可以在线create index还可以开并行,但是这个我觉得操作比统计信息重太多了。等低峰时候在做,告知他先等等。在这期间我想到了直方图。发现了点问题。这个时间怎么才两个桶?不科学啊。

难道说让我遇到了可遇不可求的高级问题?经常看高手们如何推算统计信息以及玩转数据分布,这次终于有机会看看了。不过多年工作中Oracle的统计信息和直方图一直很给力,虽然看到过一些极端案例有问题,但是我自己没遇到过。后来我让他尝试了我的想法,给出了直方图的更改。
直方图针对列做了以后终于不是2个了,达到了我的预期。再过来看执行计划,快哭了。还是依旧。在直方图做的时候顺带也在线重建索引了。也就是说中高低端的手法基本都用了,没效果。我估计今天要折在这里了。
好吧,既然如此怎么都不给面子,那么就抱着最后一丝希望让我们来看看这些数据长什么样子吧?抽了10条数据一看。

很好很好。原来样本数据说明了一切。我让开发把语句改成了。
SELECT * FROM log a WHERE a.create_time >= to_date('2021/08/01', 'yyyy/mm/dd') AND a.create_time <= to_date('2021/08/30', 'yyyy/mm/dd')。这次结果是我们预期的了。
主要原因是有些程序写入的时候时间格式不是标准的格式,而我们用标准格式去查到了年以后就是比/和-后面都没有用了。所以这就是之前为什么直方图就2个。只有2020和2021。即使我强刷直方图也没用。好在这个表没有即使/又是-的。
虽然解决了,差点以为是妖孽问题。要是只处理后台我估计就无法解决了,最后是实地考察解决了问题。Oracle的统计信息和直方图还是给力的。当然MySQL和PG这些也是可以的。
