汇知百科
白蓝主题五 · 清爽阅读
首页  > 系统软件

数据库索引是否越多越好 使用技巧与常见问题解析

很多人在优化数据时,第一反应就是加索引。查询慢?加个索引试试。但索引真不是越多越好,就像家门口的快递柜,放几个方便取件,要是整栋楼全是快递柜,走路都费劲。

索引的作用:让查询更快

索引的本质是为数据建立“目录”。比如你在图书馆找一本书,如果没有分类目录,就得一本本翻。有了索引,数据库就能快速定位到目标记录。常见的 B+ 树索引能让查询从全表扫描变成几毫秒内完成。

比如有张用户表 user,按手机号查信息:

SELECT * FROM user WHERE phone = '13800138000';

如果 phone 字段没有索引,就得扫完整张表。加上索引后,查询速度可能从 2 秒降到 0.02 秒。

索引的代价:写操作变慢,存储占用上升

每增加一个索引,数据写入时就要同步更新多个结构。INSERT、UPDATE、DELETE 都会变慢。因为不只是改数据行,还得维护所有相关索引树。

举个例子,你往订单表插一条数据,如果这个表有 5 个索引,那这条记录要在主键索引、用户ID索引、时间索引、状态索引、商品ID索引里各插入一次。相当于搬一次家要通知五个亲戚,效率自然下降。

另外,每个索引都占磁盘空间。一张千万级的表,一个普通二级索引可能多占几百MB甚至上GB空间。服务器硬盘不是大风刮来的,尤其云服务按量计费,成本实实在在。

冗余索引和重复索引的问题

有些开发图省事,给 (user_id) 加了索引,又给 (user_id, status) 加一个,结果前者被后者覆盖,(user_id) 单独查询时也能用复合索引,前面那个单列索引就成了摆设。

更麻烦的是,MySQL 虽然能用最左前缀匹配复合索引,但顺序很重要。比如有索引 (a,b,c),查询 WHERE b=1 是用不了这个索引的,得从 a 开始。

什么时候该建索引?

优先给经常出现在 WHERE、JOIN、ORDER BY 里的字段加。比如登录频繁查用户名,那就给 username 加;排序常按创建时间,就考虑给 create_time 建索引。

但也要看数据分布。如果某个字段只有两个值,比如性别(男/女),加索引意义不大,因为筛选效果差,俗称“选择性低”。

监控和清理才是关键

线上系统应该定期检查哪些索引从来没被用过。MySQL 可以通过 performance_schema 查索引使用情况。长时间没被访问的索引,可以考虑删除。

有个电商后台,订单表建了七八个索引,后来发现其中三个一年都没被任何 SQL 用上,删掉之后写入性能提升了 15%,还省了 2GB 存储。

索引不是一劳永逸的东西。业务变化了,SQL 改写了,原来有用的索引可能变鸡肋。定期 review 比盲目添加更重要。