你有没有遇到过这种情况:系统用着用着就变慢了,点个列表页面要转好几秒?后台一查,发现是数据库查询拖了后腿。其实很多时候,问题不在数据量大,而在于索引没建对。
别乱建索引,先看查询语句
很多人一上来就给每个字段都加索引,觉得“反正多建点也没坏处”。其实不对。索引越多,写入速度越慢,因为每次插入、更新都要维护索引树。正确的做法是:先分析你的高频查询语句。
比如你经常按用户手机号查订单:
SELECT * FROM orders WHERE phone = '13800138000';
那就在 phone 字段上建索引。但如果这个字段本身重复值很多(比如性别、状态),那单独建索引效果就很差。
联合索引要注意顺序
如果你的查询条件经常是“用户ID + 订单状态”,那就考虑建联合索引:
CREATE INDEX idx_user_status ON orders (user_id, status);
注意顺序很重要。数据库会从左到右匹配索引,所以 user_id 必须在前。如果只查 status,这个索引就用不上。
避免在索引字段上做计算
下面这条 SQL 看似没问题,但会让索引失效:
SELECT * FROM users WHERE YEAR(create_time) = 2024;
因为你在 create_time 上用了函数,数据库没法直接用索引查找。应该改成:
SELECT * FROM users WHERE create_time >= '2024-01-01' AND create_time < '2025-01-01';
这样就能走索引了。
适当使用覆盖索引
如果一个索引包含了查询所需的所有字段,数据库就不需要回表查数据行,速度会快很多。比如你只需要查用户ID和姓名:
SELECT id, name FROM users WHERE age = 25;
可以建一个包含这三个字段的索引:
CREATE INDEX idx_age_name ON users (age, id, name);
这样查询可以直接从索引中拿到结果,不用再去找数据行。
定期检查冗余和未使用的索引
有些索引建了之后,可能根本没人用。这些“僵尸索引”白白占用空间,还影响写入性能。可以用数据库自带的工具查看索引使用情况。比如 MySQL 的 information_schema.STATISTICS 表,或者通过 performance_schema 分析。
删掉那些长时间没被使用的索引,能明显减轻数据库负担。特别是开发过程中临时加的测试索引,上线后记得清理。
小表不一定需要索引
有些配置表、字典表,总共就几十条数据,每次全表扫描也很快。这种情况下加索引反而增加维护成本。别把简单问题复杂化。
优化索引不是一劳永逸的事。随着业务发展,查询模式会变,原来的最优索引可能不再适用。定期 review 查询慢的日志,结合执行计划分析,才能让数据库一直跑在快车道上。