MySQL 索引明明在却走了全表:一次隐式类型转换的排查
【摘要】 一条主键查询突然慢了 600 倍,索引在却没用上。用 EXPLAIN 定位到隐式类型转换,顺手整理了几种常见的索引失效场景。
一条按主键查的 SQL,平时 2ms,某天突然变成 1.2 秒。看 SQL 本身没改,索引也在,最后发现是传参类型不对,触发了隐式转换。
一、先用 EXPLAIN 看真实执行计划
EXPLAIN SELECT * FROM orders WHERE order_no = 20241101001;
如果 type 是 ALL、rows 接近全表、key 为 NULL,说明索引没走。明明 order_no 上有索引,为什么不用?
二、隐式转换会让索引失效
order_no 是 varchar,但传进来的是数字。MySQL 会按「字符串转数字」的规则比较,等价于对字段做了函数运算,索引直接作废。
-- 失效
WHERE order_no = 20241101001
-- 生效
WHERE order_no = '20241101001'
反过来,字段是 int 而传字符串 '123',是可以走索引的,因为转换发生在常量侧。这一点常被记反。
三、怎么系统性找出来
- 打开慢查询日志:
slow_query_log=ON,long_query_time=0.5。 - 用
pt-query-digest汇总,按Rows_examined排序。 - 对 Top SQL 逐条
EXPLAIN,重点看type与key。
四、还有几种同类陷阱
- 字段上做运算:
WHERE DATE(create_time) = '2024-11-01',改成范围查询。 - 前导通配:
LIKE '%abc',索引无能为力。 - 联合索引不满足最左前缀。
- 字符集不一致的 JOIN,同样触发转换。
结论:索引没走,先怀疑类型和函数,而不是先去加索引。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)