这是 Beta 探索课程,内容结构、实验步骤和示例可能会继续调整。
索引优化
那次数据库崩溃
还记得我第一次实现的订单超时检查吗?
2024 年 3 月的一天,订单量达到 80 万单。早上 10 点,运维群里突然炸锅:
“数据库 CPU 100%!” “所有查询都卡住了!” “用户无法下单!”
我慌了,登录数据库一看,那个定时任务的查询正在扫描 80 万条订单记录。
慢查询日志
数据设计要点
- 查询目标是快速定位状态、任务或资源,避免在关键路径上做大范围扫描。
这个查询每分钟都在执行,数据库当然扛不住!
索引基础
什么是索引?
索引就像书的目录,可以快速找到需要的内容,而不必翻遍整本书。
数据设计要点
- 查询目标是快速定位状态、任务或资源,避免在关键路径上做大范围扫描。
索引的类型
| 类型 | 说明 | 适用场景 |
|---|---|---|
| 主键索引 | 唯一标识记录 | 主键字段 |
| 唯一索引 | 值必须唯一 | 手机号、身份证 |
| 普通索引 | 最常用的索引 | 查询条件字段 |
| 联合索引 | 多个字段的组合 | 多条件查询 |
| 全文索引 | 文本搜索 | 搜索功能 |
联合索引设计
最关键的问题
数据设计要点
- 核心是在
delay_tasks里保存业务事实,而不是把规则散落在应用逻辑里。- 索引服务于高频查询,重点是缩小扫描范围,而不是堆更多字段。
- 关键字段包括
id、task_id、execute_at、status,它们决定后续查询和管理能力。
索引设计原则
原则 1:最左前缀原则
数据设计要点
- 索引服务于高频查询,重点是缩小扫描范围,而不是堆更多字段。
- 查询目标是快速定位状态、任务或资源,避免在关键路径上做大范围扫描。
原则 2:索引覆盖查询
数据设计要点
- 索引服务于高频查询,重点是缩小扫描范围,而不是堆更多字段。
- 查询目标是快速定位状态、任务或资源,避免在关键路径上做大范围扫描。
原则 3:选择性和基数
数据设计要点
- 这里关注数据模型和约束关系,不需要记住具体语法。
实战索引优化
场景 1:订单超时查询
数据设计要点
- 核心是在
orders里保存业务事实,而不是把规则散落在应用逻辑里。- 索引服务于高频查询,重点是缩小扫描范围,而不是堆更多字段。
- 查询目标是快速定位状态、任务或资源,避免在关键路径上做大范围扫描。
- 关键字段包括
id、user_id、product_id、status、created_at,它们决定后续查询和管理能力。
场景 2:延时任务查询
数据设计要点
- 核心是在
delay_tasks里保存业务事实,而不是把规则散落在应用逻辑里。- 索引服务于高频查询,重点是缩小扫描范围,而不是堆更多字段。
- 查询目标是快速定位状态、任务或资源,避免在关键路径上做大范围扫描。
- 关键字段包括
id、task_id、task_type、task_data、execute_at、retry_count、created_at、updated_at,它们决定后续查询和管理能力。
索引维护
定期分析索引
数据设计要点
- 索引服务于高频查询,重点是缩小扫描范围,而不是堆更多字段。
- 查询目标是快速定位状态、任务或资源,避免在关键路径上做大范围扫描。
删除无用索引
数据设计要点
- 索引服务于高频查询,重点是缩小扫描范围,而不是堆更多字段。
- 查询目标是快速定位状态、任务或资源,避免在关键路径上做大范围扫描。
重建碎片化索引
数据设计要点
- 这是一次表结构演进:随着业务能力增加,把新状态、新时间点或新归属关系补进数据模型。
- 索引服务于高频查询,重点是缩小扫描范围,而不是堆更多字段。
- 查询目标是快速定位状态、任务或资源,避免在关键路径上做大范围扫描。
想一想
思考 1
如果查询条件中有 execute_at >= NOW() AND execute_at <= NOW() + INTERVAL 1 HOUR,如何设计索引?
参考答案
问题分析:
这是一个范围查询,查询未来 1 小时内将要执行的任务。
数据设计要点
- 查询目标是快速定位状态、任务或资源,避免在关键路径上做大范围扫描。
索引设计:
数据设计要点
- 索引服务于高频查询,重点是缩小扫描范围,而不是堆更多字段。
为什么方案 1 更好?
最左前缀原则:
方案 1:idx_execute_status (execute_at, status)
├─ 先按 execute_at 过滤(范围查询)
└─ 再按 status 过滤
✅ execute_at 的范围查询可以直接利用索引
方案 2:idx_status_execute (status, execute_at)
├─ 先按 status 过滤(等值查询)
└─ 再按 execute_at 过滤(范围查询)
⚠️ 虽然也能用,但不够高效最佳实践:
数据设计要点
- 索引服务于高频查询,重点是缩小扫描范围,而不是堆更多字段。