1. 慢SQL优化实战背景
去年接手公司订单系统优化时,发现一个典型问题:随着订单量突破千万级,后台报表查询经常出现超时。最严重的一条统计SQL执行时间长达8秒,直接导致管理后台卡死。通过EXPLAIN分析发现,这条查询竟然进行了全表扫描,在5000万行数据中过滤出需要的300条记录。
订单表作为电商系统的核心数据载体,其查询效率直接影响运营决策时效性。一个需要等待8秒才能看到的昨日销售报表,显然无法满足现代电商的运营需求。这促使我们不得不重新审视整个订单表的索引设计策略。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 订单表结构现状分析
2.1 现有表结构问题
我们的订单表主要包含以下关键字段:
sql复制CREATE TABLE `orders` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`order_no` varchar(32) NOT NULL,
`user_id` bigint(20) NOT NULL,
`product_id` bigint(20) NOT NULL,
`status` tinyint(4) NOT NULL COMMENT '1待支付 2已支付 3已发货 4已完成',
`amount` decimal(10,2) NOT NULL,
`create_time` datetime NOT NULL,
`update_time` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_order_no` (`order_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
现有索引仅包含主键id和订单号order_no的普通索引。当执行如下统计查询时:
sql复制SELECT COUNT(*) FROM orders
WHERE status = 2
AND create_time BETWEEN '2023-01-01' AND '2023-01-31'
由于缺乏合适的复合索引,MySQL优化器选择全表扫描而非索引查找。在5000万行数据中,status=2的记录约占总量的15%,时间范围内的记录约占5%,理论上通过索引可以快速定位到约75万行数据。
