导航首页 » 计算机 » 数据库查询慢?索引优化没那么难,几个实战案例给你讲清楚
数据库查询慢?索引优化没那么难,几个实战案例给你讲清楚

前阵子有个项目上线后出现性能问题,页面加载动不动就超时。一开始以为是代码写得烂,后来查了半天,发现是数据库索引没做好。

 

说实话,索引这东西说简单也简单,说复杂也复杂。很多开发者知道要加索引,但加在哪些字段、怎么加、加了之后会不会有副作用,这些其实都有讲究。今天就用几个实际遇到的案例来聊聊。

 

一、最基本的原则:where条件和join字段要加索引

 

这个可能很多人都知道,但实际开发中还是会漏。举个例子:

 

SELECT * FROM orders WHERE user_id = 123 AND status = 1

 

这种查询,user_id和status都应该加索引。但要注意,如果查询条件是AND关系,最好建联合索引,而不是单独建两个索引。为什么?因为MySQL一次查询只能用一个索引(大多数情况下),联合索引的效率更高。

 

联合索引的顺序也有讲究,要把区分度高的字段放前面。比如status只有0和1两个值,区分度就很低;user_id有成千上万个值,区分度就高。所以应该建(user_id, status)而不是(status, user_id)。

 

二、别忽略ORDER BY和GROUP BY

 

很多时候我们只注意WHERE条件,忘了ORDER BY和GROUP BY也需要索引。特别是数据量大的时候,file sort真的会很慢。

 

SELECT * FROM articles ORDER BY create_time DESC LIMIT 10

 

这种查询,create_time最好有索引,不然每次都要全表扫描再排序,性能可想而知。

 

三、索引不是越多越好

 

有个项目之前维护的人给每个字段都加了索引,结果INSERT和UPDATE慢得要死。因为每次写入数据都要更新索引,索引越多,写入越慢。

 

建议:一个表的索引数量控制在5个以内,超过这个数就要好好考虑一下了。

 

四、小心索引失效的情况

 

这个坑我踩过。建了索引,但查询还是走全表扫描,后来才发现是索引失效了。常见的失效场景:

 

1. 使用函数或表达式

   WHERE DATE(create_time) = \'2024-01-01\'

   这样写索引会失效,应该改成范围查询

 

2. 隐式类型转换

   字段是varchar,但查询用了int类型的值,MySQL会自动转换类型,索引就失效了

 

3. LIKE以通配符开头

   WHERE name LIKE \'%张三\'

   这种写法索引不生效,但\'张三%\'是可以的

 

4. OR条件有一边没索引

   如果OR两边的字段不是都有索引,整个索引都会失效

 

五、一个实际案例

 

有个报表查询,一次要查好几分钟。看了下SQL,大概是这样:

 

SELECT * FROM logs WHERE DATE(create_time) = CURDATE() AND type IN (1,2,3)

 

问题很明显:DATE函数让create_time的索引失效了,type字段没索引。

 

优化方案:

1. 把DATE(create_time)改成范围查询:create_time >= CURDATE() AND create_time < CURDATE() + INTERVAL 1 DAY

2. 给type字段加索引

 

改完之后,查询时间从3分钟降到了200毫秒。

 

六、定期检查索引使用情况

 

建了索引不代表就万事大吉了,要定期看看索引的使用情况。MySQL有个sys库,可以查到哪些索引从来没被用过:

 

SELECT * FROM sys.schema_unused_indexes;

 

对于那些从来没被用过的索引,可以考虑删掉,省得浪费资源。

 

索引优化是个需要持续关注的事情,不是一劳永逸的。希望这些案例能对你有帮助。