MySQL频繁更新列建索引价值判断及读写权衡计算方法
频繁更新列(如
lastUpdatedOn)加索引的价值判断 不存在普适的对错结论,完全取决于业务的读写场景:
- 值得加的场景:存在高频查询以该列为过滤条件、排序条件,比如查询近3天更新的用户数据、按更新时间倒序分页拉取列表,这类场景下无索引会触发全表扫描,开销远大于索引带来的额外写成本
- 不值得加的场景:几乎没有查询会用到该列作为查询条件,仅作为数据更新的埋点字段存储,这类场景下索引只会凭空增加写操作的 overhead,没有任何收益
索引收益与开销的权衡计算方法
核心判断逻辑为:索引的总读收益 > 索引带来的总写开销时,建索引就是合理的,可从以下维度量化计算:
1. 读收益计算
先统计单位时间内(如1小时)所有用到该列作为查询条件的请求次数,记为读QPS * 时长。
单条读请求的开销节省 = 无索引时的查询IO开销 - 加索引后的查询IO开销:
- 无索引时通常为全表扫描,开销等于扫过的表数据页数量(如果是大表,很容易达到上千甚至上万次IO)
- 加索引后为二级索引B+树查询,时间复杂度为O(lgN),通常仅需要1~3次IO即可定位到目标数据
总读收益 = 单条读开销节省 * 单位时间内读请求总次数
2. 写开销计算
统计单位时间内所有会更新lastUpdatedOn字段的写请求次数,记为写QPS * 时长。
单条写请求的新增开销 = 二级索引更新的平均IO开销:
- 常规更新场景下,需要1~3次IO完成B+树定位+值更新
- 若出现索引页分裂/合并的极端场景,会额外增加25次IO,这类场景出现概率通常低于10%,可以平摊到单次写开销中,最终单条写的平均新增开销约为24次IO
总写开销 = 单条写新增开销 * 单位时间内写请求总次数
简化经验类比
如果不抠IO差异,把单次B+树操作(读/写)等价为1个成本单位,判断规则可以简化为:单条读收益 * 读请求量 > 单条写开销 * 写请求量
你提到的“读写比大于2:1则收益为正”的示例,本质是单条读收益为2单位、单条写开销为1单位的场景下的特例,这个类比逻辑在数据结构层面是成立的。
实操验证方案
如果无法精准统计读写开销,可以在线上低峰期先临时加索引,观察24小时内的核心指标变化:慢查询数量是否下降、写操作的平均响应时间涨幅是否在可接受范围、整体系统吞吐量是否上升,若符合预期则可以保留索引,反之删除即可。
内容的提问来源于stack exchange,提问作者Mohit Singh
相关产品推荐
相关产品推荐

