MySQL查询运行过慢如何优化?附待优化查询语句
优化你的MySQL多关联+GROUP_CONCAT慢查询
嘿,看了你的查询语句,慢的核心原因很明显:多个LEFT JOIN会先生成超大的中间结果集,再加上一堆GROUP_CONCAT(DISTINCT)的去重操作,直接把数据库的CPU和IO拉满了。下面给你几个实操的优化方案,一步步来:
1. 拆分聚合逻辑,先聚合再关联
别把所有表一股脑JOIN起来再做聚合,先给每个需要聚合的关联表单独做子查询聚合,再和主表item关联。这样能把中间结果集的大小砍到原来的几分之一。
举个调整后的写法(根据你的查询结构补全了逻辑):
SELECT item.*, cat.category, col.Color, sub.Sub_category, unit_data.Unit, unit_data.Unit_value, gst.HSN AS GST_hsn, base_unit.Name AS Base_unit FROM item LEFT JOIN gst ON gst.ID = item.GST_hsn LEFT JOIN base_unit ON base_unit.ID = item.Base_unit_ID -- 假设你的关联字段是这个 -- 先聚合分类信息 LEFT JOIN ( SELECT ic.Item, GROUP_CONCAT(DISTINCT c.English_name) AS category FROM item_category ic LEFT JOIN category c ON c.ID = ic.Category GROUP BY ic.Item ) cat ON cat.Item = item.ID -- 先聚合颜色信息 LEFT JOIN ( SELECT ic.Item, GROUP_CONCAT(DISTINCT ic.Color) AS Color FROM item_color ic GROUP BY ic.Item ) col ON col.Item = item.ID -- 先聚合子分类信息 LEFT JOIN ( SELECT ic.Item, GROUP_CONCAT(DISTINCT sc.English_name) AS Sub_category FROM item_category ic LEFT JOIN sub_category sc ON sc.ID = ic.Sub_category GROUP BY ic.Item ) sub ON sub.Item = item.ID -- 先聚合单位和单位值信息 LEFT JOIN ( SELECT iu.Item, GROUP_CONCAT(DISTINCT u.Name) AS Unit, GROUP_CONCAT(DISTINCT iu.Value) AS Unit_value FROM item_unit iu LEFT JOIN unit u ON u.ID = iu.Unit GROUP BY iu.Item ) unit_data ON unit_data.Item = item.ID
每个子查询只处理自己的关联表,聚合后再和主表关联,数据量瞬间小很多。
2. 给关联字段加索引,让JOIN和GROUP BY飞起来
索引是解决慢查询的核心,你得确保这些字段有索引:
- 主表
item的ID(主键默认有,但确认下) - 所有关联表的外键字段:比如
item_category.Item、item_color.Item、item_unit.Item、gst.ID、base_unit.ID - 用于JOIN的关联字段:比如
item_category.Category、item_category.Sub_category、item_unit.Unit - 子查询里
GROUP BY的字段(比如Item)也要加索引
举几个创建索引的例子:
-- 给item_category加复合索引,覆盖JOIN和GROUP BY CREATE INDEX idx_item_category_item_cat ON item_category(Item, Category); CREATE INDEX idx_item_category_item_subcat ON item_category(Item, Sub_category); -- 给item_color加索引 CREATE INDEX idx_item_color_item ON item_color(Item); -- 给item_unit加复合索引 CREATE INDEX idx_item_unit_item_unit ON item_unit(Item, Unit);
3. 能删DISTINCT就删,别让数据库白干活
先检查你的关联数据:比如item_category里同一个Item和Category会不会有多条重复记录?如果没有,那GROUP_CONCAT里的DISTINCT完全可以删掉!去重操作非常耗资源,能省则省。
4. 别乱用LEFT JOIN,能用INNER JOIN就换
如果某些关联表的数据是必填的(比如每个item一定有对应的base_unit),把LEFT JOIN改成INNER JOIN,数据库会更早过滤掉无效数据,减少结果集大小。
5. 用EXPLAIN查瓶颈,精准优化
跑一下EXPLAIN命令看看你的查询执行计划,重点找Using filesort、Using temporary这些标记,这些就是性能瓶颈:
EXPLAIN SELECT `item`.*, GROUP_CONCAT(DISTINCT category.English_name) AS category... -- 你的完整查询
通过执行计划,你能看到哪个表没用到索引,哪个步骤开销最大,然后针对性调整。
6. 分页查询记得加LIMIT
如果你的查询是用来分页或者只需要部分数据,一定要加LIMIT,别一次性处理全表数据,比如:
... LIMIT 100;
内容的提问来源于stack exchange,提问作者shah rushabh
相关产品推荐
相关产品推荐

