餐饮企业 MySQL 千万级订单查询优化实践
业务背景
随着门店数量突破 2000 家,公司的中央订单库 (orders 表) 数据量单月新增超过 3000万 条。在每月末进行全国大区营业额聚合分析时,商业智能(BI)平台频繁出现超时断连,一条包含 GROUP BY 与多表 JOIN 的复杂报表 SQL 耗时高达 12 秒。
性能瓶颈分析
通过 EXPLAIN 指令,我们定位到核心问题:
- 索引失效:查询条件中对
created_at字段使用了函数DATE(created_at)。 - 临时表与文件排序:由于
GROUP BY store_id并没有命中组合索引,MySQL 在磁盘上创建了庞大的临时表 (Using temporary; Using filesort)。
优化方案落地
1. 消除函数索引依赖
我们将原有代码逻辑:
SELECT store_id, SUM(total_amount)
FROM orders
WHERE DATE(created_at) = '2026-05-01'
GROUP BY store_id;
修改为基于范围查询(走 B+ 树索引):
SELECT store_id, SUM(total_amount)
FROM orders
WHERE created_at >= '2026-05-01 00:00:00'
AND created_at < '2026-05-02 00:00:00'
GROUP BY store_id;
2. 构建黄金组合索引
根据最左前缀匹配原则,我们为该查询创建了联合索引 idx_created_store:
ALTER TABLE orders ADD INDEX idx_created_store (created_at, store_id, total_amount);
此举不仅消除了 filesort,同时实现了覆盖索引 (Covering Index),引擎可直接从索引树中读取 total_amount,避免了耗时的回表 (Bookmark Lookup) 操作。
结果收益
优化上线后,全国大区聚合报表的 P99 耗时从 12.4s 骤降至 180ms。报表拉取变得如同丝般顺滑,大幅提升了管理层的决策效率。