GROUP BY 實際上包含排序操作,與 ORDER BY 類似,故可利用索引優化。MySQL 有三種實現方式,前兩種利用索引,第三種退化為臨時表+排序。
條件:查詢欄位為索引前綴,且無 WHERE / JOIN / 子查詢干擾。
CREATE INDEX idx_gid_uid_gc ON group_message(group_id, user_id, gmt_create); DROP INDEX idx_group_message_gid_uid ON group_message;
EXPLAIN SELECT user_id, MAX(gmt_create) FROM group_message WHERE group_id < 10 GROUP BY group_id, user_id\G -- 關鍵輸出 Extra: Using where; Using index for group-by
(group_id, user_id, gmt_create) 已按分組鍵排序MIN()、MAX()、COUNT(*) (特定條件)Using index (無 for group-by)Using temporary; Using filesort| 場景 | 索引設計建議 | 預期模式 |
|---|---|---|
| 單表 GROUP BY + MIN/MAX | 索引包含 (group_col, agg_col) | 鬆散索引掃描 |
| 單表 GROUP BY + COUNT/SUM | 索引包含 (group_col, ...) | 緊湊索引掃描 |
| 多表 JOIN + GROUP BY | 驅動表分組欄位建索引 | 視情況退化 |
| WHERE 過濾 + GROUP BY | 複合索引 (where_col, group_col) | 緊湊/鬆散 |
EXPLAIN SELECT ... GROUP BY ...; -- 關注 Extra 欄位: -- Using index for group-by → 鬆散掃描 (最佳) -- Using index → 緊湊掃描 (良好) -- Using temporary; Using filesort → 需優化 (最差)