记一次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

可以看到内表关联是走索引的,搞定。

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