mysql group by 執行原理及千萬級別count 查詢優化

2023-11-17 18:00:35

大家好,我是藍胖子,前段時間mysql經常碰到慢查詢報警,我們線上的慢sql閾值是1s,出現報警的表資料有 7000多萬,經常出現報警的是一個group by的count查詢,於是便開始著手優化這塊,遂有此篇,記錄下自己優化過程中的心得。

優化慢sql前,肯定是要懂sql的查詢邏輯,所以我先介紹下group by 語句的執行邏輯。

group by 執行邏輯

環境準備

拿下面這張表舉例,這是一張記錄資料夾id和使用者id關聯關係的表。其中dir_id代表資料夾id,uid代表使用者id,還有個唯一索引是uniq_dir_id。

create table t_dir_user
(
id bigint unsigned auto_increment
primary key,
dir_id bigint default 0 not null,
uid bigint default 0 not null,
constraint uniq_dir_id
unique (dir_id, uid)
)

表一共有7000多萬的資料。下面開始介紹使用group by 語句時sql執行的原理。

沒有用到索引的情況

先說下結論,group by後面的列如果不能使用上索引,那麼則會產生臨時表且很可能產生檔案排序的情況。

group by 語句有分 使用到索引和沒有使用到索引的情況,先看看沒有使用到索引的情況。假如我想查詢在一些資料夾範圍內,使用者關注的資料夾數量。那我可以寫出下面這樣的sql。

explain select count(1), uid  
from t_dir_user  
where dir_id in (1803620,4368250,2890924,2033475,3038030)  
group by uid;

使用explain分析時,會發現這個查詢是使用到索引的,且Extra 那一欄會出現下面的資訊。

Using index condition; Using temporary; Using filesort

上述資訊代表了查詢是使用到了索引來做where條件查詢,並且使用到了臨時表和檔案排序。

注意