各位网友,大家好,我是黄伟老师。
今天内容的主题是:另辟蹊径的一则SQL优化案例
一共分4个部分:
问题现象
分析问题
解决问题
简单小结
一 问题现象
21号早上,收到项目组诉求,业务系统的某个模块从20号下午3:30左右出现有数据插入失败的情况。希望能从数据库端或者服务器上看看有没有异常现象,并给予支持。
登录到数据库控制台上,经过初步排查发现,看到下述现象:
从20号上午10:29开始,系统频繁出现类似插入SQL,且每次执行耗时1秒。更为糟糕的是,该类型SQL一直持续到今天早上,不停的在执行。
二 分析问题
拎出其中一条SQL进行分析:
对应的参数为:
显然,该SQL的目的是要向表t_ai_prd_history_effective_record进行有条件的插入数据,其条件是表中不存在
的情况下。具体体现在SQL中的WHERE NOT EXISTS。
那么,问题就明了了,应该是出现在NOT EXISTS的子查询上。
接下来,单独看看这个子查询的执行计划:
t_ai_prd_history_effective_record表数据量:
意料之中,每次执行这个去重的不存在判断,都对这个拥有300多万条数据的t_ai_prd_history_effective_record表执行一次全表扫描,可想而知,执行效率肯定低下,每次耗时1秒多,且随着该表的数据不断增多,插入的速度将变得越来越慢。
这里,可以说是,每一条记录的插入,都将导致下一次插入变得更慢!
三 解决方案
找到了问题的症结,就要着手优化了。
终极目标就是怎么可以绕过那个NOT exists的子查询?
经过和项目组同事讨论,给出下述两种方案:
能不能对于t_ai_prd_history_effective_record表的子查询的那6个字段上建立一个唯一性索引,如果可以的话,那么我们就在插入的时候不再需要那个where条件判断去重了,而由这个唯一性索引的约束去做判断,如果插入重复数据的话,就违反约束,报错抛出异常。这样的话,看似解决了这个问题,但是,如果从业务上考虑的话,的确是存在过多的重复数据,如果报错的话,业务人员会在系统上频繁的收到报错信息,不是很友好。
既然这样的话,那问题就变的更简单了。直接粗暴的把SQL的where not exists的去重判断删掉,先一股脑儿的插入,不论是否重复,然后,写个批处理的SQL,放到晚上再统一把重复的记录删掉,问题不就解决了嘛。
给出一个删除PostgreSQL数据库表重复记录的示例:
四 简单小结
发现并找到慢SQL的问题所在,进行有针对性的优化改造,解决问题往往不一定难,深入思考一下多尝试。
以上,给出SQL优化的一个思路和方向。
最后,如果你喜欢我的视频,欢迎关注我的公众号:
请帮我转发分享给更多的朋友,谢谢收看,再见。
领取专属 10元无门槛券
私享最新 技术干货