本文已参与「新人创作礼」活动,一起开启掘金创作之路
今天看到一个库的cpu告警,去看了下top sql就发现了一个奇葩的SQL。
不得不吐槽下,都2022年了,还有在索引列上用函数的写法。。
其实也很好理解这个SQL是希望查询时间列是当天(current_date)的,但是由于该时间列是timestamp类型的,而current_date的结果是date类型的,所以开发人员将这两个时间用函数进行了截断。
那这个SQL该怎么优化呢,可能大部分人第一反应是加个函数索引不就好了,不过说实话函数索引大部分都显得有些多余,尤其是该列上都已经存在一个索引了,那么我们有没有什么办法对这个SQL进行等价改写呢?
进行SQL等价改写关键其实在于了解需求,而这个SQL的需求很简单:获取时间是当天的数据。
因此该SQL可以改写为:
条件改成了r.occur_time >= current_date and r.occur_time < current_date+1,,改写完之后用上了索引,cost从289238降到了5,时间也是大大降低。
看上去不等的写法其实相等,说白了等价改写其实最主要的是了解需求!
这让我想到了之前一个十分经典的等价案例:
begin
select count(*) into v_cnt from t1 ;
if v_cnt>0
then …A逻辑….
else
then …B逻辑…..
End;
这个需求大致如下:
获取t1 表的记录数,判断是否大于0,如果大于0走A逻辑,否则就走B逻辑。 因此代码就如上所示来实现了,可真正的需求是这样吗?
其实应该是这样的:只要T1表有记录就走A逻辑,否则走B逻辑。
两者有区别吗?其实区别还是很大的,前者可是强调获取记录数,我们是不是一定要遍历整个表得出一个记录数才知道是否大于0?
真正需求的理解可以让我们这样实现,只要从T1表中成功获取到第一条记录,就可以停止检索了,表示该表有记录了,难道事实不是这样?
因此原先的SQL可以修改为:
begin
select count(*) into v_cnt from t1 where rownum=1;
if v_cnt=1
then …A逻辑….
else
then …B逻辑…..
End;
总结:
有的时候优化SQL了解需求也是一大捷径,需要考虑将需求最小化,具备少做事的意识乃是顶级优化。