通過聯合索引優化MYSQL慢查詢
一、慢SQL分析
慢SQL如下
SELECT SUM(t.amount) as amount FROM (SELECT game_id,room_id,is_robot,amount,record_time FROM t_statements_logs WHERE game_id = 30 AND is_robot = 0 ORDER BY record_time DESC)t
GROUP BY t.room_id ORDER BY t.record_time DESC LIMIT 20;
執行時間通常在1S以上
表索引情況如下:
查詢執行計劃
EXPLAIN
SELECT SUM(t.amount) as amount FROM (SELECT game_id,room_id,is_robot,amount,record_time FROM t_statements_logs WHERE game_id = 30 AND is_robot = 0 ORDER BY record_time DESC)t
GROUP BY t.room_id ORDER BY t.record_time DESC LIMIT 20;
執行計劃如下
key爲game_Index命中了game_Index索引
Using index condition; Using temporary; Using filesort:表示使用了索引查詢,並使用了臨時表和內存排序
rows:375574
二、SQL優化分析
從以上情況看掃描的數據過多導致執行時間變長,可根據record_time限制掃描的數據範圍
修改game_Index索引,增加record_time字段
修改後的SQL
SELECT SUM(t.amount) as amount FROM (SELECT game_id,room_id,is_robot,amount,record_time FROM t_statements_logs WHERE game_id = 30 AND is_robot = 0 AND record_time > '2020-03-09 00:00:00' ORDER BY record_time DESC)t
GROUP BY t.room_id ORDER BY t.record_time DESC LIMIT 20;
由於業務是根據record_time降序取前20條,通常一個game_id最近一個月產生的room_id會超過20條,所以查詢數據時間範圍限制到最近一個月;假如當前時間爲:2020-04-09 00:00:00,往前推一個月爲:2020-03-09 00:00:00。
新SQL執行計劃結果
key_len變成了85,說明record_time也使用了索引
新SQL執行時間已經變成了8ms