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