频繁写入的表加索引反而拖慢性能
在一些业务系统中,比如日志记录、用户行为追踪这类高频插入的表,如果给它们加上过多索引,实际是给自己挖坑。每次插入一条数据,数据库不仅要写入原始数据,还得同步更新所有相关的索引树。就像你在微信发朋友圈,本来点一下就发出去了,结果系统还要求你同时更新好友列表、点赞排行、浏览统计三个榜单,速度自然就下来了。
比如一张每天新增百万条记录的操作日志表,如果在 create_time 字段上建了索引,每插入一条都要调整 B+ 树结构,磁盘 I/O 压力明显上升。这时候你会发现,写入速度从每秒 5000 条掉到不到 2000 条,问题很可能就出在索引上。
数据重复度高的字段加索引效果差
有些字段本身区分度很低,比如“性别”只有男和女,“状态”字段常见“启用”“禁用”两种值。在这种字段上建索引,查询时数据库还是得扫描大量重复节点,起不到过滤作用。好比你去机场接人,只知道对方坐的是南航飞机,但当天有 20 班南航航班到达,这个信息根本没法帮你快速定位。
执行下面这样的查询:
SELECT * FROM users WHERE status = 'active';即使 status 有索引,MySQL 可能仍然选择全表扫描,因为满足条件的数据占了表的 80% 以上,走索引反而多了一次回表开销。
小数据量的表没必要建索引
一张只有几百行的配置表,比如存储网站开关选项的 settings 表,加索引纯属多余。数据量小的时候,全表扫描可能只需要一次磁盘读取,而走索引还得先查索引页再查数据页,等于绕远路。
就像你找家里遥控器,客厅就三件家具,直接一个个翻最快,没必要先查“遥控器存放地图”再行动。
经常更新的字段不适合作为索引
如果某个字段像“余额”一样被频繁修改,那么它上面的索引也会被不断调整。每一次 UPDATE 都可能导致索引树分裂、页合并,带来额外的维护成本。这种情况下,不仅写操作变慢,还可能引发锁争用,影响并发性能。
例如:
UPDATE accounts SET balance = balance + 100 WHERE user_id = 123;若 balance 是索引列,这次更新就会触发索引变更,而实际上我们很少会按余额范围来查询用户。
组合索引设计不合理时适得其反
有些人为了“保险”,给多个字段建了组合索引,比如 (a, b, c),但实际查询只用了 b 或 c。由于索引最左匹配原则,这种查询无法命中索引,白白浪费了存储和维护成本。
就像你有一把钥匙串,顺序是门禁卡、办公室钥匙、抽屉钥匙,但你总想先用抽屉钥匙开门,显然行不通。
更糟的是,这种无效索引还会占用内存,挤占真正有用的索引空间,导致缓存命中率下降。