文章目录
- 业务背景
- 初版查询SQL
- ==这段SQL有什么问题呢==
- 执行计划
- 实际执行
- 初次优化
- 执行计划2
- 实际执行
- 继续优化
- 再次优化的SQL
- 执行计划3
- 实际执行
- 疑问
业务背景
我上篇文章介绍了一个规则引擎的简单使用,主要就是为了众包业务批量录入数据的一些校验的统一管理,
很快就派上了用途,需要新增一个规则
针对录入的每条数据,需要查询历史数据作为对比,看看是存在相同的数据,然后进行限制
这个需求简单分析下前提
1.批量数据录入,如果单条数据查询过长,肯定是不能接受的
2.查询数据所需参数很多,单独为了这次查询建很多索引,不现实。
所以只能从SQL本身来进行优化
3.表的数据量大概百万级别
初版查询SQL
主表A,关联三个业务子表,
根据主表的一个varchar类型的字段(实际存储格式为时间,前期设计是由外部系统传入的)以及其他多个参数
进行分月查询前几个月存在相同的数据的个数,
然后进行校验
这段SQL有什么问题呢
1.子查询问题,
2.or语句问题
如下图所示
执行计划
通过控制台看执行计划
cost很大,有三个子查询
实际执行
实际更新导预发环境时,也可以看到执行时长很不理想 在50ms上下徘徊,
假如有500条数据需要校验,单独这条规则就需要25s左右的时间,
无论是技术层面还是业务层面都是不可接受的
SQL优化的一个重要原则就是尽量减少子查询,优先使用内连接来代替子查询
初次优化
1.使用inner join 代替子查询
2.使用union all 代替or ,注意避免使用union 会导致排序去重的消耗
第一次优化sql如下
执行计划2
cost明显降低
但是存在另一个问题:group by 导致排序sort,存在大量的开销
实际执行
可以看到在拆分掉子查询之后,sql执行耗时已经稳定在== 10ms==以下了
继续优化
既然第一次优化存在group by导致的sort问题
那么考虑将group by去掉(有日期限制,不存在大量需要分组的数据) 看看有没有性能的提升
还有将SQL函数去掉,在代码层面对数据进行截取去重
再次优化的SQL
执行计划3
可以看到cost 已经降低到极低的水平
实际执行
实际执行也有很大提升 在5ms左右
疑问
为什么PostgreSQL语句去掉Group by还有函数之后,SQL语句的执行效率提升不是很明显(10ms -> 5ms)
有猛男大手子可以评论区滴滴我
有没有可能搞到1ms