sql中用group by去重查询优化记录


好久没写笔记了,来记一次优化sql的过程。


需求

对一张数据量约200万条的表进行单表查询,需要对app_id这个字段去重,只保留每个app_id的最新一条记录。

我的思路

因为数据库里设置了ONLY_FULL_GROUP_BY,使得select的字段只能与group by的字段相同,或是使用聚合函数,所以不能直接用下面的sql:

select * from t group by app_id order by date DESC

且在这张表中,id越大数据越新,因此先在一个子查询里用group by分组去重,取出每组的最大id,再用in判断即可,sql大致如下。

select * from t where id in 
(select max(id) from t group by app_id)

问题

执行后发现查询时长11s,给app_id加上索引后缩短为4s。

4s的时长还是很影响使用体验,需要继续优化。

排查过程

首先思考的可能性是子查询效率太低,或许是max()拖慢了速度,但单独执行子查询后发现时长仅为0.1s,再看了下整个sql的解释信息:

image-20220209142044601

问题源头出来了,这200万条数据居然没有走索引!

然后又查了下资料,发现in不会走索引,它会老老实实扫全表。

于是这只能放弃in了呀。

解决方法

因为子查询出来的数据量相对较小,只有300多条,因此将in替换为left join,原先子查询的表作为主表。

SELECT t2.* 
FROM ( 
SELECT max( id )
FROM t 
GROUP BY t.app_id) t1
LEFT JOIN t t2 ON t1.id = t2.id

查询时长约为0.2s,撒花~


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM