实用百科指南
霓虹主题四 · 更硬核的阅读氛围

数据库索引不适合的场景 实用操作步骤与避坑指南

发布时间:2025-12-10 07:17:14 阅读:329 次

频繁写入的表加索引反而拖慢性能

你有没有遇到过这种情况:某个业务模块查询变快了,但整体系统却越来越卡?特别是像日志记录、用户行为追踪这类每秒都在写数据的表,如果盲目加上索引,每次 INSERT 或 UPDATE 都得同步更新索引树,磁盘 I/O 直接拉满。比如一个电商后台的“用户点击商品”表,每天几百万条新增,如果在“操作时间”字段建了索引,写入速度可能直接腰斩。

索引不是免费的,它要维护额外的数据结构。写多读少的场景下,这个代价往往大于收益。

数据量太小的表不需要索引

一张只有几百条记录的配置表,比如“省份列表”或者“订单状态码”,全表扫描也就几毫秒的事。这时候加个索引,不仅查询没快多少,还白白占用了存储空间。就像去邻居家借杯 sugar,犯不着先打电话预约再开车过去。

MySQL 在执行小表查询时,优化器甚至会直接忽略索引,走全表扫描。所以别看别人说“加索引就快”,得看具体情况。

重复值太多的列建索引效果差

比如用户表里的“性别”字段,只有“男”和“女”两个值,就算建了索引,查“所有女性用户”时,数据还是要扫一半的数据页。这种低基数(low cardinality)字段,索引的选择性太差,优化器大概率不会用它。

类似的情况还有“是否已读”、“状态标志”这种布尔类字段,除非你是按极少数值查询(比如查所有未读消息),否则索引帮助有限。

经常变更的字段不适合作为索引

假设有个“用户积分”字段,频繁被更新。如果你在这个字段上建了索引,每次积分变动,数据库不仅要改数据行,还得调整 B+ 树结构,甚至引发页分裂。长期下来,索引会变得碎片化,查询效率下降,还得定期重建。

更糟的是,如果复合索引里包含了这种高频更新字段,整个索引的维护成本都会升高。

使用函数或表达式查询时索引失效

比如你经常这样查数据:

SELECT * FROM users WHERE YEAR(create_time) = 2023
即使 create_time 上有索引,这种写法也会导致索引失效,因为数据库得先对每个值计算 YEAR() 函数。正确的做法是写成范围查询:
SELECT * FROM users WHERE create_time >= '2023-01-01' AND create_time < '2024-01-01'
否则索引白建了。

字符串字段的前缀索引不一定划算

给一个长文本字段比如“用户备注”建完整索引,占用空间巨大。很多人会建前缀索引,比如只取前10个字符。但这样容易造成哈希冲突,查询时还得回表比对,反而多了一次磁盘读取。而且前缀索引无法用于 ORDER BY 或 GROUP BY,功能受限。

不如想想,是不是真有必要在这类字段上做快速查询?也许全文搜索引擎更适合。