单表索引超过6个会导致高并发写入性能断崖式下降,因InnoDB需同步更新多棵B+树引发写放大、锁竞争加剧及优化器失效;应通过系统视图、区分度分析和执行计划识别冗余低效索引,并以高频组合查询设计最左前缀联合索引。

单表索引数量超过6个,高并发写入性能大概率会断崖式下降——这不是阈值警告,而是InnoDB引擎的物理约束直接导致的写放大问题。
为什么6个是实际拐点,而不是理论上限
MySQL InnoDB对单表最多支持64个二级索引,但“能建”不等于“该建”。每多一个索引,INSERT/UPDATE/DELETE就必须同步更新一棵独立的B+树。27个索引的表(真实案例)在高峰期写入延迟飙升,根本原因不是CPU或磁盘慢,而是每次插入都要做27次B+树路径查找+页分裂+脏页刷盘。
关键影响点包括:
- 写入开销呈线性增长:6个索引时,索引维护可能占写操作总耗时的60%;到12个时轻松突破90%
- 锁竞争加剧:多个索引更新需在不同B+树上加锁,事务间更容易因锁顺序不一致触发死锁(错误码
1213) - 优化器选索引变“盲选”:索引过多时,
EXPLAIN显示key为空或type=ALL的概率显著上升,因为优化器放弃穷举而退化为全表扫描
怎么判断当前索引是否冗余或低效
别只数数量,先看哪些索引实际没人用、哪些在拖后腿。执行以下检查:
- 查未使用索引:
SELECT * FROM sys.schema_unused_indexes WHERE object_schema = 'your_db' AND object_name = 'your_table'; - 查低区分度字段:
SELECT COUNT(DISTINCT status)/COUNT(*) AS selectivity FROM order_ext;,若结果(如状态字段只有3个值),这个单列索引基本无效 - 查重复覆盖:
SHOW INDEX FROM your_table;,如果已有idx_user_id_status,再建idx_user_id就是冗余 - 查写入热点:
SELECT rows_affected, sql_text FROM performance_schema.events_statements_history_long WHERE sql_text LIKE '%INSERT INTO your_table%';,结合慢日志看哪些索引字段频繁出现在WHERE中
联合索引设计必须满足最左前缀,且要砍掉“幻觉索引”
开发常误以为“多建几个单列索引就能覆盖各种查询”,结果反而让写入雪上加霜。真实高频查询往往是组合条件,比如 WHERE user_id = ? AND status IN (1,2) AND create_time > ?。
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
正确做法是:
- 把过滤性最强、查询频率最高的列放在联合索引最左侧,例如
(user_id, status, create_time) - 删除所有以该联合索引开头的单列或前缀索引,如
idx_user_id、idx_user_id_status - 避免“函数索引幻觉”:不要为了
WHERE DATE(create_time) = '2024-01-01'单独建create_time索引,改用范围查询create_time BETWEEN '2024-01-01 00:00:00' AND '2024-01-01 23:59:59'+ 联合索引 - 字符串字段慎用全字段索引:
VARCHAR(255)建索引优先考虑前缀长度,如INDEX idx_name (name(191)),但必须验证SELECT COUNT(DISTINCT LEFT(name,191))/COUNT(*)是否足够区分
上线前必须做的三件事
索引删减不是拍脑袋决定的,尤其在高并发写入场景下:
- 用
pt-query-digest或慢日志分析过去7天真实SQL,确认删掉的索引确实没被任何SELECT或UPDATE ... WHERE引用 - 在从库或影子库上执行
ALTER TABLE your_table DROP INDEX xxx;,观察写入TPS和平均延迟变化,对比前后SHOW ENGINE INNODB STATUS中log sequence number增速 - 保留回滚能力:删索引前先备份
SHOW CREATE TABLE结果,避免紧急恢复时手忙脚乱
真正卡住性能的,往往不是数据量本身,而是那些没人查、却每秒被更新几十次的索引。删索引比加索引更需要勇气,也更见功底。










