news 2026/9/2 23:26:41

拼多多三面挂了!问 “索引明明建了,为什么不生效?”,我背了最左前缀,面试官:你只懂皮毛。

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
拼多多三面挂了!问 “索引明明建了,为什么不生效?”,我背了最左前缀,面试官:你只懂皮毛。

昨天帮一个 5 年经验的大厂兄弟复盘拼多多三面,他也是一脸懵逼。

面试官给了一个真实的线上事故场景:“我们有一张 500 万数据的用户表,phone字段加了普通索引。有一天,运营跑来反馈说查询巨慢。DBA 一看,发现一条简单的SELECT * FROM user WHERE phone = 13800001234居然走了全表扫描(ALL),把数据库 CPU 打满了。你觉得是为什么?”

这兄弟下意识地回答:

  1. “是不是用了LIKE '%...'?”(面试官:是等值查询)

  2. “是不是用了OR?”(面试官:单条件查询)

  3. “是不是phone列上有函数?”(面试官:SQL 很干净,没加函数)

兄弟彻底没辙了:“那...那就是 MySQL 抽风了?”

面试官叹了口气:“你对隐式类型转换和成本优化器(CBO)一无所知。”

其实,“索引失效”绝不仅仅是 SQL 写法的问题,更多时候是数据分布类型定义挖的坑。

今天带你拆解 MySQL 索引失效的3 个“隐形杀手”,全是书上不怎么讲,但线上天天发生的血案。

杀手一:隐式类型转换(最坑爹的低级错误)

回到上面那个面试题。为什么phone = 13800001234会全表扫描?

真相是:在数据库定义里,phone字段通常是VARCHAR类型(为了存前导0或者兼容性)。 但是!开发人员在写 SQL 时,为了省事,直接写了数字(没加引号):

-- 你的 SQL(埋雷版)SELECT*FROMuserWHEREphone=13800001234;

MySQL 的内心 OS:

“你给我传了个数字,但表里是字符串。那我得把表里的字符串转成数字才能比较啊!” 于是,SQL 等价于:

-- MySQL 实际执行的 SQLSELECT*FROMuserWHERECAST(phoneASUNSIGNED)=13800001234;

后果:索引列上被加了函数!

B+ 树的结构是按字符串排序的,不是按转换后的数字排序的。一旦在索引列上用了函数,B+ 树就废了。全表扫描,卒。

⚠️ 关键防杠细节(反向不失效):

如果面试官反问:“那如果字段是INT,我传了字符串'123'会失效吗?”

答案是:不会失效!因为 MySQL 会把输入的常量字符串转成数字,它动的是输入参数,没动数据库字段,所以索引依然有效。

  • String列传Int->

  • Int列传String->。 记死这个结论,面试能救命。

杀手二:回表成本太高,MySQL 弃用索引(反直觉)

场景复现:有一张表t_orderstatus字段加了索引。 SQL:SELECT * FROM t_order WHERE status > 1

  • 情况 A:表里有 100 条数据,满足条件的有 10 条。 ->走索引

  • 情况 B:表里有 100 万条数据,满足条件的有 90 万条。 ->全表扫描(不走索引)

面试官问:为什么数据量大了反而不走索引?

真相(CBO 成本计算):MySQL 的优化器是基于成本(Cost)的。

  1. 走索引的成本= 搜索二级索引树 +回表(随机 IO)

  2. 不走索引的成本= 全表扫描(顺序 IO)。

如果满足条件的数据太多(比如超过 30%),回表的代价(90 万次随机 IO)远远大于全表扫描的代价。 优化器非常聪明,它会觉得:“折腾那一趟干啥?直接扫表算了。”

✅ 避坑指南:别以为建了索引就一定会被用。如果你的查询结果集很大(区分度不高),索引就是个摆设。

优化方案:尽量使用覆盖索引SELECT status, id ...),去掉SELECT *。只要不需要回表,MySQL 就会强制走索引了。

杀手三:Order By 导致的文件排序(FileSort)

场景复现:联合索引idx_a_b_c (a, b, c)。 SQL:SELECT * FROM t WHERE a = 1 ORDER BY c

很多人以为:a用到了索引,c也在索引里,应该没问题吧?”

真相:索引失效(部分),触发 FileSort。根据最左前缀原则,索引的排序是:先按 a 排,a 相同按 b 排,b 相同按 c 排。中间跳过了b,直接按c排序? B+ 树里,跨过b之后,c无序的!

MySQL 没办法利用索引的顺序,只能把数据取出来,在内存(Sort Buffer)里重新排一遍。这就是Using filesort,性能杀手。

✅ 避坑指南:遵守最左匹配,不仅仅是WHEREORDER BY也要遵守。 要么ORDER BY b, c,要么WHERE a=1 AND b=常量 ORDER BY c

面试标准答案模板(直接背)

下次被问“索引失效”,别只背“最左前缀”,直接甩出这套“底层原理 + 线上实战”的组合拳:

“索引失效在生产环境中非常常见,除了基础的‘最左前缀’、‘LIKE %’之外,我认为最容易被忽视的杀手有三个:

  1. 隐式类型转换(致命):这是开发最容易犯的错。比如varchar字段传了int值,导致 MySQL 内部触发CAST函数,索引列变成了函数运算,直接导致 B+ 树失效。但反过来int字段传字符串通常是安全的。

  2. 成本优化器的选择(CBO):MySQL 选不选索引,取决于Cost(成本)。如果查询条件命中率太高(比如筛选出了 30% 以上的数据),导致回表(随机 IO)的成本超过了全表扫描(顺序 IO),优化器会主动放弃索引。解决办法是利用覆盖索引减少回表。

  3. 排序失效(FileSort):联合索引中,如果中间断层(比如WHERE a=1 ORDER BY c跳过了 b),索引的有序性就利用不上了,MySQL 必须进行文件排序。这点在做分页查询时要特别小心。

所以,分析 SQL 慢查询,不能光看有没有索引,必须结合EXPLAINtypekey_lenExtra(是否 Using filesort/index condition)来综合判断。”

老哥最后再唠两句

兄弟,数据库这块,EXPLAIN是你的亲爹。 代码写完了,上线前必须拿 EXPLAIN 跑一遍。 看到type = ALL,赶紧改; 看到Extra = Using filesort,赶紧改; 看到key_len不对(没完全命中联合索引),赶紧改。

别信什么“理论上应该走索引”,MySQL 优化器有时候比你想象的“聪明”,也比你想象的“蠢”。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/2 23:07:20

【Springboot】数据层开发-数据源自动管理

Spring Boot 数据源自动管理是 Spring Boot 约定优于配置核心思想的典型体现,无需手动编写数据源,框架通过自动配置机制,自动识别数据库依赖、加载连接配置、创建最优的数据源实例,并装配事务管理器、JdbcTemplate 等配套组件&…

作者头像 李华
网站建设 2026/9/2 22:29:10

基于单片机LM2596开关稳压电源控制设计

2稳压开关电源的基本原理 2.1稳压开关电源的组成模块 1 、稳压模块 2、负载接入指示灯模块 3、调压电路 4 、RC消尖峰电路 5、二极管续流电路 6、 过流保护电路 2.2稳压开关电源的基本原理 把220V交流市电通过整流二极管整流、各种电容滤波之后变成直流,再通过MOSFE…

作者头像 李华
网站建设 2026/9/2 22:26:17

基于open stack构建私有云计算平台

二、企业初期现状及需求分析 (一)锐科企业管理平台建设现状 1.企业拓扑结构图2-1 锐科企业现状网络拓扑图 三、企业私有云解决方案 (一)开源云平台选择 目前主流的云平台有CloudStack和OpenStack。 C1oudStack是一个开源的具有高可用性及扩展性的云计算平台,CloudSt…

作者头像 李华
网站建设 2026/9/2 23:06:05

阿里云部署智普Open-AutoGLM实战指南(从零到上线全流程解析)

第一章:阿里云部署智普Open-AutoGLM概述在人工智能与大模型快速发展的背景下,智普推出的 Open-AutoGLM 作为一款面向自动化机器学习任务的大语言模型工具链,正逐步成为开发者构建智能应用的核心组件。依托阿里云强大的计算资源与弹性服务能力…

作者头像 李华
网站建设 2026/9/2 22:27:02

Java毕设选题推荐:基于springboot的健身爱好者线上互动与打卡社交平台系统基于springboot的大学生健身爱好者交流网站【附源码、mysql、文档、调试+代码讲解+全bao等】

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华