1. 工单系统性能问题背景与挑战
最近接手了一个为1000名工人设计的工单系统性能优化项目。这个系统已经运行了两年多,随着业务量增长,最近频繁出现查询超时和页面卡顿的情况。特别是在每天上午9-10点的工单提交高峰期,系统响应时间经常超过5秒,严重影响了工人的工作效率。
通过初步排查发现,数据库中存在大量执行时间超过2秒的慢查询。最严重的一条工单状态查询SQL,执行时间竟然达到了8.7秒。对于一个需要实时处理工单状态的系统来说,这种性能表现是完全不可接受的。
1.1 系统现状分析
当前工单系统的主要数据表包括:
- work_order(工单主表):约120万条记录
- worker_info(工人信息表):约1000条记录
- department(部门表):30条记录
- work_order_operation(工单操作日志表):约350万条记录
系统主要瓶颈出现在以下几个场景:
- 工人查看自己待处理的工单列表
- 管理员按部门/状态筛选工单
- 工单状态变更时的级联更新
- 工单历史记录查询
1.2 性能问题根源定位
使用EXPLAIN分析慢查询日志后,发现主要问题集中在:
- 缺少合适的联合索引,导致全表扫描
- 存在大量filesort临时表排序
- 部分查询没有利用到索引覆盖
- 索引设计不合理,区分度低的字段放在索引前列
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 索引优化原理与实战策略
2.1 MySQL索引工作原理深入解析
理解索引的工作原理是优化的基础。MySQL的InnoDB引擎使用B+树索引结构,这种数据结构有以下几个关键特性:
- 多路平衡搜索树:保证查询时间复杂度为O(log n)
- 叶子节点存储完整数据记录:通过主键聚簇
- 非叶子节点只存储索引键和指针:减少IO次数
以一个简单的工单表为例:
sql复制CREATE TABLE work_order (
id BIGINT PRIMARY KEY,
worker_id INT,
status TINYINT,
create_time DATETIME,
content VARCHAR(200)
);
如果我们为(worker_id, status)创建联合索引,索引结构大致如下:
code复制 [根节点]
/ | \
[worker_id=1] [worker_id=2] [worker_id=3]
/ \ / \ / \
[status=0] [status=1] ... ... ...
2.2 联合索引设计黄金法则
根据工单系统的查询模式,我们总结出以下索引设计原则:
-
最左前缀匹配原则:索引(a,b,c)可以用于查询a、a,b或a,b,c条件的查询,但不能用于b或c单独查询
-
区分度优先原则:将区分度高的字段放在索引前面。计算区分度
