MySQL LEFT JOIN关联子查询性能过慢,如何优化?
嗨,我来帮你搞定这个查询慢的问题!这种子查询单独跑很快,但关联后就卡的情况,我遇到过好多次,大多是因为关联环节缺少有效索引,或者查询里藏着没必要的冗余操作。咱们一步步来优化:
第一步:先砍掉冗余的关联和无效语句
仔细看你的原查询,最后那个LEFT JOIN tblB on tblB.id = tblC.maxid完全是多余的——你既没在SELECT里取tblB的字段,也没在WHERE里用到它,留着只会多做一次无意义的表关联,拖慢速度。另外WHERE 1和最后的GROUP BY tblA.id(如果tblA.id是主键/唯一值的话)也是多余的,直接去掉就行。
精简后的基础查询:
SELECT tblA.id FROM tblA LEFT JOIN ( SELECT invid, max(id) as maxid, group_concat(testcase) as testgrp FROM tblB GROUP BY invid ) AS tblC ON tblC.invid = tblA.id;
第二步:给关键字段加复合索引,从根源提速
子查询单独快,但关联后慢,核心原因是子查询生成的临时表(tblC)和tblA关联时,或者子查询本身的分组计算没有合适的索引支撑。咱们给tblB加一个复合索引,同时确保tblA的id有索引:
- 给
tblB创建复合索引:
这个索引能让子查询里的CREATE INDEX idx_tblB_invid_id ON tblB(invid, id);GROUP BY invid和max(id)直接通过索引快速计算,不用全表扫描,同时也能让group_concat(testcase)的效率更高。 - 确保
tblA.id是主键(一般主键默认自带索引),如果不是的话,给它加主键或普通索引:ALTER TABLE tblA ADD PRIMARY KEY (id);
第三步:如果还是慢,试试重写子查询为窗口函数(可选)
如果你的MySQL版本是8.0及以上,可以用窗口函数替代子查询分组,避免生成临时表的开销。这种方式在数据量较大时,优化器的执行计划会更高效:
SELECT DISTINCT tblA.id FROM tblA LEFT JOIN ( SELECT invid, max(id) OVER(PARTITION BY invid) as maxid, group_concat(testcase) OVER(PARTITION BY invid) as testgrp FROM tblB ) AS tblC ON tblC.invid = tblA.id;
不过这一步是锦上添花,前面两步做好后基本就能解决大部分问题了。
额外小提示:查看执行计划定位瓶颈
如果做完上面的优化还是有问题,你可以用EXPLAIN查看执行计划,看看哪一步是全表扫描(type列显示ALL),针对性地加索引:
EXPLAIN SELECT tblA.id ... -- 把你的查询放这里
内容的提问来源于stack exchange,提问作者Alireza
相关产品推荐
相关产品推荐

