記一次MySQL子查詢in不走索引優化

最近在項目裏面將Druid的SQL監控打開,發現了一個慢SQL查詢,單表查詢數據只有幾萬條,執行數據居然要2s,SQL如下

SELECT * FROM instance_metric WHERE id in (select min(id) from instance_metric GROUP BY code )

explain分析SQL

看起來沒什麼問題,子查詢過濾出重複記錄,返回最小id ,in 後面接入的是id,數據很快纔對的啊。使用explain 分析執行過程,結果大失所望

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 PRIMARY instance_metric NULL ALL NULL NULL NULL NULL 619621 100.00 Using where
2 SUBQUERY instance_metric NULL ALL NULL NULL NULL NULL 619621 100.00 Using temporary

可以看出in 後面並沒有走索引查詢,走了全表掃描,很納悶。

正常in接參數

直接使用id 放入in 括號中

EXPLAIN select * from instance_metric WHERE id in (1,2,3);

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE instance_metric NULL range PRIMARY PRIMARY 4 NULL 3 100.00 Using where

執行結果沒問題的,查詢是走索引的

使用表關聯代替in

本來想着使用exists代替in 使用,發現exists好像寫不出來,不知道怎麼取到最大值、最小值比較。當沒有辦法時,冷靜來想想使用id來過濾重複記錄,爲什麼不使用表關聯呢,我的是個天才啊😀。

EXPLAIN select i.* from instance_metric i inner JOIN (select min(id) id from instance_metric GROUP BY code ) t1 on t1.id = i.id

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> NULL ALL NULL NULL NULL NULL 10 100.00 Using where
1 PRIMARY i NULL eq_ref PRIMARY PRIMARY 4 t1.id 1 100.00 NULL
2 DERIVED instance_metric NULL ALL NULL NULL NULL NULL 10 100.00 Using temporary

可以看到內表關聯是走索引的,搞定。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章