跳转到主内容
极星编程网:以代码为星,赴技术山海!

mysql索引过多如何影响写入性能_mysql索引维护与成本评估

索引越多,INSERT/UPDATE/DELETE越慢,因每新增记录需同步更新所有相关索引的B+树,引发插入定位、页分裂、指针调整及磁盘刷盘等开销,高并发下易成瓶颈。 索引越多,INSERT/UPDATE/DELETE 越慢 每新增一条记录,MySQL 不只是写数据行,还要同步更新所有相关索引的 B+ 树结构。每个索引都是一份独立的、有序的数据副本,写入时都要做插入定位、页分裂、指针调整甚至磁盘刷盘。尤其在高并发写入场景下,索引维护开销会直接变成瓶颈。 常见错误现象:
INSERT
延迟突然升高;
SHOW PROCESSLIST
里大量线程卡在
update
或
insert
状态;
innodb_row_lock_waits
指标明显上升。 每多一个二级索引,写操作至少多一次随机 I/O(尤其是非缓存命中时) 唯一索引还要额外校验重复值,比普通索引更重
TEXT
/
VARCHAR(255)
类字段建索引,若实际值很长,索引页膨胀快,分裂更频繁 联合索引顺序不合理(比如把低区分度字段放前面),会导致索引树深度增加,写入路径变长 如何判断哪些索引是“冗余”或“无效”的 不是所有索引都在被用。很多是历史遗留、开发随手加、或只在某次慢查里临时加完就忘了删。真正有效的索引,应该有稳定且可衡量的查询收益,否则就是纯成本。 使用场景:线上表已运行数月,但没人定期看索引使用情况。 查
sys.schema_unused_indexes
(MySQL 8.0+),它基于 performance_schema 统计,能直接列出长期未被任何查询使用的索引 用
SELECT * FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = 'db' AND TABLE_NAME = 't';
对比
INDEX_NAME
和实际
EXPLAIN
中出现的索引,找“从不出现”的 注意联合索引的前缀覆盖:如果已有
(a,b,c)
,再建
(a,b)
就是冗余;但
(b,a)
不一定冗余,因为最左前缀匹配规则不同 唯一索引和主键冲突?
SHOW CREATE TABLE t
看是否有多个
UNIQUE KEY
约束同一组字段 ALTER TABLE DROP INDEX 的实际影响和安全前提 删索引不是“立刻变快”,而是释放后续所有写入的开销。但操作本身会锁表(MySQL 5.6+ 的
ALGORITHM=INPLACE
可避免全表锁,仍需元数据锁等待),且不可逆——删错可能让某条关键查询从 10ms 慢成 10s。 MySQL(Linux) MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。 下载 参数差异:
DROP INDEX idx_name ON t
在 MySQL 5.7 默认走
INPLACE
,但若索引包含全文或空间类型,则强制
COPY
;MySQL 8.0 默认更激进,但仍建议显式加
ALGORITHM=INPLACE, LOCK=NONE
并观察执行时间。 务必先在从库或影子库上跑一遍,确认没业务报错(比如应用层依赖
DUPLICATE KEY
异常做逻辑分支) 避开高峰期,
pt-online-schema-change
可绕过锁表,但会延长操作时间,且对大表容易拖垮复制延迟 删完立刻查
information_schema.STATISTICS
验证,别只信命令返回的
Query OK
监控删索引后
Innodb_buffer_pool_read_requests
和
Innodb_buffer_pool_reads
是否同步下降——说明查询确实不再依赖该索引了 单列索引 vs 联合索引:选哪个更省写入成本 三个单列索引
(a)
、
(b)
、
(c)
和一个联合索引
(a,b,c)
,写入开销差得远。前者要维护三棵 B+ 树,后者只一棵,但查询能力不一定弱——关键看 WHERE 条件怎么组合。 性能影响:联合索引写入压力≈单个单列索引,但能覆盖更多查询模式;而三个单列索引会让每次写入触发三次独立的树维护流程。 优先按高频查询条件排序建联合索引,例如经常查
WHERE a=1 AND b>10
,就建
(a,b)
,别拆成两个单列 区分度高的字段放前面(如
user_id
),低区分度的放后面(如
status
),能减少树的无效分支 不要为了“看起来全面”建
(a,b,c,d,e)
—— 超过 4 列的联合索引,写入放大明显,且很少有查询真能用满全部列 注意
ORDER BY
和
GROUP BY
字段是否能被同一联合索引覆盖,否则排序/分组会额外触发 filesort 索引成本藏在每次写入的毫秒级延迟里,积少成多才压垮系统。最危险的不是没索引,而是有一堆没人敢动、也没人记得为什么存在的索引。

相关文章