数码工坊
白蓝主题五 · 清爽阅读
首页  > 表格技巧

数据库索引字段顺序真的有影响吗?别让查询慢得像蜗牛

做后台开发或者写报表的时候,你有没有遇到过查一条数据要等好几秒的情况?明明加了索引,为啥还是这么慢?问题可能就出在索引字段的顺序上。

索引不是随便加,顺序决定效率

比如你有一张用户订单表,经常按用户ID和下单时间查数据。你建了个联合索引:(user_id, created_at)。这时候执行下面这句SQL:

SELECT * FROM orders WHERE user_id = 123 AND created_at > '2024-01-01';

这条能用上完整的索引。但如果你把条件反过来,先筛时间再看用户ID:

SELECT * FROM orders WHERE created_at > '2024-01-01' AND user_id = 123;

看起来一样,其实执行计划可能完全不同。因为索引是按字段顺序组织的,B+树先排user_id,再在每个user_id下排created_at。如果查询不带user_id,直接跳到created_at,那就没法走索引的前半段,只能全扫描或部分使用。

最左前缀原则,别踩坑

MySQL的联合索引有个“最左前缀”规则。比如你建了(a, b, c)这个索引,只有以下几种情况能命中:

  • 只查 a
  • 查 a 和 b
  • 查 a、b、c
  • 查 a 和 c(虽然c中间断了,但某些优化器也能部分利用)

但如果你只查b,或者b和c,那这个索引基本废了,数据大概率会选择全表扫描。

实际例子:为什么换了顺序就变快了?

之前有个同事写了个统计接口,查某个时间段内某类用户的订单数,SQL写着没问题,但一跑就5秒起。一看索引,居然是(created_at, user_id, status)。可他查询时只固定了user_id和status,created_at是个范围查询。结果索引只能用上user_id之前的字段,后面全失效。

改成(user_id, status, created_at)之后,同样SQL执行时间降到0.1秒。不是数据库玄学,是顺序决定了哪些条件能快速定位。

选择性高的字段放前面?不一定

很多人说“要把区分度高的字段放前面”,比如性别就不如用户ID区分度高。这话对一半。真正关键的是你的查询条件怎么写。即使user_id区分度高,但如果你的业务80%都是按status查,那status放前面反而更合适。

字段顺序得跟着查询模式走,别照搬教科书。

小建议:看看你的慢查询日志

打开慢查询日志,找到执行时间长的语句,用EXPLAIN看看有没有用上索引。如果type是index或ALL,很可能就是索引顺序没配好。调整一下,有时候比加硬件还管用。

索引字段顺序不是小事,它直接决定了数据库能不能快速锁定你要的数据。别以为加了索引就万事大吉,顺序不对,等于白搭。