如何优化MySQL中针对频繁变动字段建立索引带来的维护开销?

星萱同学_7100

星萱同学_7100

2026-07-21

792人浏览

原创

频繁更新字段加索引严重损伤写入性能:只要该字段出现在update的set子句且属于任一二级索引,innodb就必须同步重写整条索引记录,实测qps下降30%~60%,锁等待激增。

如何优化mysql中针对频繁变动字段建立索引带来的维护开销?

频繁更新字段加索引到底有多伤写入

直接说结论:只要字段出现在 UPDATE 的 SET 子句里,且它在任一二级索引中(单列或复合索引的任意位置),InnoDB 就必须同步重写整条索引记录。这不是“稍微慢点”,而是每次更新都触发 B+ 树节点定位、页内重排、redo log 写入、undo log 生成——实测 QPS 下降 30%~60%,innodb_row_lock_waits 暴涨,SHOW PROCESSLIST 里卡在 Updating 状态的线程明显增多。

常见误判是只看 WHERE 条件是否用到该字段。真正致命的是字段本身“动得勤”:比如 status、updated_at、version、score 这类每笔业务必改的字段。哪怕你只改一行、只改一个字段,只要它在索引里,开销就逃不掉。

怎么快速识别该删哪个索引

别猜,用数据说话。先执行:

SHOW INDEX FROM t;

重点标出满足以下全部条件的索引:

  • 非主键、非唯一约束(Non_unique = 1)
  • 字段更新频率 ≥ 1 次/秒(可通过应用日志或 performance_schema.events_statements_summary_by_digest 估算)
  • 该字段在 WHERE 中几乎不用(查慢查询日志或 EXPLAIN 结果,确认无 type=ref 或 range 依赖它)

临时验证手段不是设 INVISIBLE——那只是骗优化器,InnoDB 依然照常维护。正确做法是:

MySQL
MySQL

编写正确的MySQL查询,避免字符集、索引和锁方面的常见陷阱。

下载
  • 备份后执行 ALTER TABLE t DROP INDEX idx_status
  • 用真实流量压测 5 分钟,观察 sys.schema_table_statistics 中 updates 延迟是否下降 ≥30%
  • 如果回升明显,说明这就是瓶颈索引,别犹豫,删掉

复合索引里放更新字段有多危险

联合索引不是“多个字段堆一起”,而是按顺序构建一棵树。只要其中任意字段被更新,整条索引项就得重写。尤其当高频变动字段放在靠前位置时,问题更严重:

  • (updated_at, user_id):每次时间戳变,整条索引全重写,等价于每行更新都引发页分裂
  • (status, created_at):哪怕 created_at 从不更新,只要 status 变,整个索引节点都要刷新
  • 字段数超 3 个(如 (user_id, status, updated_at)):索引体积大 + 更新频次高 = 写放大成倍放大

安全做法是把稳定字段放最左,比如 (user_id, created_at),再单独为 status 加索引(仅当读远多于写且无更好过滤条件时);或者把变动字段拆解,例如用生成列 updated_day DATE AS (DATE(updated_at)),再建 INDEX idx_updated_day ON t (updated_day)。

覆盖索引在高频更新场景下可能适得其反

覆盖索引确实能省回表,但代价是索引更大、更新更重。对日均百万级 UPDATE 的表,它往往让写性能雪上加霜:

  • 检查 performance_schema.table_io_waits_summary_by_index_usage,确认该索引的 COUNT_READ 是 COUNT_WRITE 的 10 倍以上才值得保留
  • 避免用覆盖索引去加速 UPDATE ... SET amount = amount + 1 WHERE order_id = ? 这类操作——索引里存了 amount,每次加法都得同步更新索引
  • 真要查得快,优先考虑冗余字段 + 应用层双写,比如在 users 表里存 total_points 并建索引,而不是在日志表 user_points_log 的 change_amount 上硬扛索引

最常被忽略的一点:索引维护成本不是静态的。随着数据量增长和更新模式变化,昨天安全的索引,今天可能已成瓶颈。定期(建议每月)用 ANALYZE TABLE 更新统计信息,并结合 performance_schema 回溯索引实际读写比,比任何“最佳实践清单”都管用。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
mysql修改数据表名
mysql修改数据表名

MySQL修改数据表:1、首先查看数据库中所有的表,代码为:‘SHOW TABLES;’;2、修改表名,代码为:‘ALTER TABLE 旧表名 RENAME [TO] 新表名;’。php中文网还提供MySQL的相关下载、相关课程等内容,供大家免费下载使用。

2023.06.20

2133

6

MySQL创建存储过程
MySQL创建存储过程

存储程序可以分为存储过程和函数,MySQL中创建存储过程和函数使用的语句分别为CREATE PROCEDURE和CREATE FUNCTION。使用CALL语句调用存储过程智能用输出变量返回值。函数可以从语句外调用(通过引用函数名),也能返回标量值。存储过程也可以调用其他存储过程。php中文网还提供MySQL创建存储过程的相关下载、相关课程等内容,供大家免费下载使用。

2023.06.21

1299

5

mongodb和mysql的区别
mongodb和mysql的区别

mongodb和mysql的区别:1、数据模型;2、查询语言;3、扩展性和性能;4、可靠性。本专题为大家提供mongodb和mysql的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.18

755

5

mysql密码忘了怎么查看
mysql密码忘了怎么查看

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql密码忘了怎么办呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.19

2872

5

mysql创建数据库
mysql创建数据库

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql怎么创建数据库呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.25

4808

4

mysql默认事务隔离级别
mysql默认事务隔离级别

MySQL是一种广泛使用的关系型数据库管理系统,它支持事务处理。事务是一组数据库操作,它们作为一个逻辑单元被一起执行。为了保证事务的一致性和隔离性,MySQL提供了不同的事务隔离级别。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2023.08.08

1099

3

sqlserver和mysql区别
sqlserver和mysql区别

SQL Server和MySQL是两种广泛使用的关系型数据库管理系统。它们具有相似的功能和用途,但在某些方面存在一些显著的区别。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.11

5071

4

mysql忘记密码
mysql忘记密码

MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。那么忘记mysql密码我们该怎么解决呢?php中文网给大家带来了相关的教程以及其他关于mysql的文章,欢迎大家前来学习阅读。

2023.08.14

4502

7

mysql事务隔离级别
mysql事务隔离级别

mysql规范中定义了四种事务隔离级别,不同的隔离级别对事务的处理有所不同。本专题为大家提供mysql事务隔离级别相关的文章内容,大家可以免费体验。

2023.08.16

5894

11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL vs MySQL
PostgreSQL vs MySQL

共1课时 | 181人学习

使用phpenv集成环境安装极致CMS
使用phpenv集成环境安装极致CMS

共2课时 | 289人学习