索引不是越多越好:给表加索引前的四个判断

举报
yd_271358468 发表于 2026/11/05 01:16:31 2026/11/05
【摘要】 一张表变慢时,最常见的第一反应是加索引。很多时候它确实管用,但也有不少时候,加完索引查询没快多少,写入却变慢了,磁盘占用还涨了一大截。索引不是免费的,它是拿写入成本、存储成本和优化器判断换来的读取加速。动手之前,先过四个判断,能省掉不少返工。判断一:这个查询真的走索引吗加索引之前,先看执行计划,确认查询条件里有没有能用上索引的列。最常见的情况是条件写在函数或表达式里,例如对日期列用函数截取年...

一张表变慢时,最常见的第一反应是加索引。很多时候它确实管用,但也有不少时候,加完索引查询没快多少,写入却变慢了,磁盘占用还涨了一大截。索引不是免费的,它是拿写入成本、存储成本和优化器判断换来的读取加速。动手之前,先过四个判断,能省掉不少返工。

判断一:这个查询真的走索引吗

加索引之前,先看执行计划,确认查询条件里有没有能用上索引的列。最常见的情况是条件写在函数或表达式里,例如对日期列用函数截取年份、对字符串列做大小写转换,索引就用不上了。还有隐式类型转换:列是字符型,查询条件却传了数字,数据库会把列逐行转换后再比较,索引同样失效。

另一个常见误判是选择性。给性别、状态这种只有两三个取值的列单独加索引,过滤效果很有限,优化器很可能直接放弃索引走全表扫描。选择性高的列,例如用户 ID、订单号,才是索引的优先候选。先算一下不同值的数量占总行数的比例,比例越高,索引越值得加。

判断二:是不是复合索引的顺序错了

多条件查询用单列索引往往不够,需要复合索引,而复合索引的列顺序决定了它能服务哪些查询。最左前缀原则说的是:查询条件必须从复合索引的第一列开始连续匹配,中间断了一列,后面的列就用不上了。

举个例子,查询条件经常是用户 ID 加时间范围,复合索引就应该是(用户 ID,时间),而不是反过来。如果把时间放前面,用户 ID 放后面,按用户查的查询就只能用到时间那一列,甚至完全用不上。建复合索引之前,把高频查询的条件列出来,按“等值条件在前、范围条件在后”的顺序排,排完再建。

等值条件在前还有一个原因:范围条件后面的列基本用不上索引排序和过滤。时间范围一旦出现,后面的列就只能靠回表过滤了。所以范围列尽量放在复合索引的最后一位。

判断三:写入和更新扛得住吗

每加一个索引,写入时就要多维护一份数据结构。插入一行,数据库除了写表本身,还要把每个索引都更新一遍;更新被索引的列时,旧索引条目要删、新条目要加。表上有五六个索引,写入就可能比原来慢一倍以上。

判断方法是看这张表的读写比。读多写少的配置表、订单历史表,加索引的收益大;写多读少的流水表、日志表,每加一个索引都是给写入加税。如果表每天写入量很大,宁可少建索引,或者把低频查询交给离线统计,而不是在主表上堆索引。

更新频率也要看。被频繁更新的列不适合单独建索引,因为每次更新都要搬动索引条目,锁的范围也可能变大。状态字段就是典型:它经常变、取值又少,建索引收益小、代价大。

判断四:有没有被忽略的覆盖索引

很多慢查询不是缺索引,而是缺“刚好够用”的索引。查询只需要三列,却因为索引只覆盖了其中一列,数据库每次都要回表查整行。把查询需要的列都放进索引,就成了覆盖索引,查询只读索引就能返回结果,不用回表,速度常常快一个数量级。

覆盖索引也不是列越多越好。索引列越多,索引本身越大,缓存命中率越低,写入代价也越高。只把高频查询真正需要的列放进去,冷门列不要凑数。一个实用的做法是:先看慢查询日志里出现最多的三到五个查询,为它们各配一个覆盖索引,而不是给每个查询都建一个。

加完之后要验证的两件事

索引建好不等于问题解决,需要验证两件事。第一是执行计划确实变了,查询走了新索引,扫描行数明显下降;第二是写入没有明显劣化,观察一段时间的写入耗时和锁等待。如果执行计划没变,可能是统计信息过旧,先更新统计信息再判断,不要急着再加一个。

索引的维护也要定期做。删除不再使用的索引和重复索引:复合索引(A,B)已经包含了单列索引(A)的能力,后者就可以删掉。定期查一次未被使用的索引,把长期没人用的清理掉,写入和存储都会轻松一些。

索引是数据库里性价比很高的优化手段,但前提是加在正确的地方。用之前先问四个问题:查询走不走它、顺序对不对、写入扛不扛得住、能不能顺手做成覆盖索引。四个都通过,再建;有一个存疑,先验证再动手。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。