你以为加了索引就快了?数据库:我谢谢你

2026-06-01 13 0

做后端开发这些年,我见过最多的迷惑行为就是:数据库一慢,加索引。查询卡了,加索引。老板问为什么这么慢,加索引。

兄弟,你加的是索引,不是魔法杖啊。

今天我要说一个大多数教程都不会告诉你的真相:你的索引,可能从一开始就没生效过

一个真实的血案

之前有个项目,用户反应用户列表加载巨慢,页面转圈转好几秒。我一看,慢查询日志里躺着一条这样的SQL:

SELECT * FROM users WHERE status = 1 AND age > 18 AND city = "北京";

表结构是这样的:

CREATE TABLE users (
  id INT PRIMARY KEY,
  name VARCHAR(50),
  status TINYINT,
  age INT,
  city VARCHAR(50),
  INDEX idx_status_age_city (status, age, city)
);

三列联合索引,完美!按理说应该很快吧?EXPLAIN走起。

结果返回的是ALL——全表扫描。

我当时的表情:

问号脸.jpg

索引明明就在那里,为什么不用?

问题出在哪里?

答案是索引列参与运算

看这条SQL:

WHERE age > 18

表面上很正常。但如果你稍微改一下:

WHERE age + 1 > 19

数据库拿到这个条件,第一反应是:我怎么知道age+1之后对应的是哪一列?索引排好序的是age的值,不是age+1的值。

所以——索引列做任何运算,索引必失效

但是!重点来了。

你可能会说,我没对age做运算啊,就一个 > 18,凭什么失效?

因为类型隐式转换

真正的凶手:类型转换

我建议你现在就打开你的数据库,执行这个实验:

EXPLAIN SELECT * FROM users WHERE phone = 13800138000;

如果你用的是MySQL,你会看到这条SQL走了全表扫描

为什么?

因为phone是VARCHAR类型,但你传的是一个数字。MySQL会把字符串转换成数字,相当于:

CAST(phone AS DOUBLE) = 13800138000

索引列做了类型转换,跟做了运算一样,索引失效。

这就是为什么我见过无数人在phone字段上建了索引,查询还是慢成狗的真正原因。

解决方法?简单:

WHERE phone = "13800138000"  -- 字符串字面量

加个引号,世界和平。

还有更阴的——函数包裹

这种情况更隐蔽:

WHERE DATE(created_at) = '2026-06-01'

created_at是DATETIME,你用DATE()函数包了一层。数据库看到这个,脑子里只有一个想法:

我排好序的是完整的时间戳,你给我的却是一个日期。我怎么知道这个日期对应哪些时间?

所以——索引列被函数包裹,索引必失效

正确写法:

WHERE created_at >= '2026-06-01 00:00:00' AND created_at < '2026-06-02 00:00:00'

或者:

WHERE created_at BETWEEN '2026-06-01 00:00:00' AND '2026-01 23:59:59'

虽然长一点,但是能走索引,值不值?

最离谱的:OR语句

看这个:

WHERE name = "张三" OR age = 25

假设name和age都有索引,这条SQL会怎么走?

答案是:只有name的索引生效,age的索引被忽略

因为OR语句要求两个条件都走索引,才能优化成索引合并。只要有一个条件不走索引,整个查询就只能用另一个索引,或者全表扫描。

解决方法?UNION:

SELECT * FROM users WHERE name = "张三"
UNION
SELECT * FROM users WHERE age = 25;

或者把OR改成UNION ALL加去重,根据你的业务场景选。

说点真正重要的

讲了这么多,有人可能会问:你说的这些我都知道了,有没有更系统的判断方法?

有。每次写完SQL,先跑一下EXPLAIN或者EXPLAIN ANALYZE,看看type列是不是ALL,key列是不是NULL。

如果type是ALL而且key是NULL——恭喜你,你的查询正在全表扫描。

还有几个我踩过坑的经验:

  • LIKE以通配符开头,如LIKE '%keyword',索引必失效
  • !=和NOT IN,大多数情况下不走索引
  • 隐式类型转换,字符串字段用数字查、数字字段用字符串查
  • 联合索引不遵循最左前缀,直接查第二列

最后说两句

加索引不是什么高深技术,每个CRUD仔都会。但理解索引什么时候失效、为什么会失效,才是真正考验功力的地方。

很多人以为性能问题是玄学,其实只是因为不了解底层原理。

下次数据库慢了,先别急着加索引,用EXPLAIN看看这条SQL到底在干什么。

说不定你就省下了改代码、加硬件的好几轮扯皮。

毕竟——

老板要的是结果,不是你加了几个索引。

相关文章

【AI探索】当小龙虾遇上AI:新闻速递、奇技淫巧与我的翻车现场
我用OpenClaw这一年:真香、踩坑与意外惊喜
懒得折腾?让小龙虾帮你一键部署AI工具,省心又省力 🦞
写API这事儿,别再把POST和GET乱搞了——我见过最离谱的接口设计
gRPC到底香不香?我扒了生产环境代码后发现了这些真相
🔥 为什么你的API总是那么慢?后端性能优化避坑指南

发布评论