MySQL 社招必考题:如何优化子查询?

B站影视 电影资讯 2025-09-23 09:11 1

摘要:大家好,我是小米,一个31岁还在互联网“搬砖”路上摸爬滚打的开发者。今天来和大家聊聊我最近经历的一场面试,主题是“MySQL子查询优化”。

大家好,我是小米,一个31岁还在互联网“搬砖”路上摸爬滚打的开发者。今天来和大家聊聊我最近经历的一场面试,主题是 “MySQL子查询优化”

说实话,这题目我一听见,心里咯噔了一下。因为子查询这东西,面试官一问,八成就是在等你掉坑。好在我这些年踩过的坑够多,顺手还能给大家写篇文章分享一下。

所以今天这篇文章,不仅仅是 面试题解析,更是 实战踩坑经验总结。如果你也正在准备社招面试,或者线上系统里SQL跑得慢得要死,这篇文章一定对你有帮助。

面试官盯着我笑了一下,开口第一句就是:

“你觉得MySQL子查询该怎么优化?”

我脑子里立刻闪回起以前因为子查询写得不当,把线上数据库搞成蜗牛的场景。那次领导狠狠批评了我一句:

“小米啊,你这是在写SQL,还是在给数据库挖坟?”

我心里那个羞愧啊!后来我硬生生啃了几本MySQL优化的书,还在项目里做了好几次实战才算明白。

于是,我对面试官微微一笑:“子查询优化啊,我能聊一整天,要听完整版吗?”

在进入优化方案之前,我们得先搞清楚: 子查询为什么容易拖垮性能?

常见问题有三:

1、嵌套太深

内层子查询每次都要重新执行,数据量一大,效率直线下降。特别是 WHERE id IN (SELECT …) 这种写法,如果子查询没索引,简直噩梦。

2、不能充分利用索引

子查询结果集经常需要临时表存放,而临时表往往没有合适的索引。

3、文件排序 & 临时表开销大

一旦涉及 GROUP BY、DISTINCT、ORDER BY,MySQL可能会开临时表甚至文件排序,速度嗖嗖掉。

这就是为什么子查询看起来优雅简洁,但实际经常跑得像蜗牛。

面试官最想听到的第一个答案就是这个:

“能不用子查询,就用JOIN代替。”

来看一个例子。

低效子查询写法:

这里的问题是:内层子查询可能会重复执行,效率低下。

改成关联查询:

这样做的好处:

避免重复扫描:JOIN会直接利用索引做匹配。优化器更聪明:JOIN查询可以用到更优的执行计划,比如索引合并、驱动表选择等。结果集更可控:方便加条件、加排序,而不是靠子查询临时表。

面试小技巧:当面试官追问时,你可以补充一句:

“如果student.id是主键,JOIN的效率会比IN快很多,尤其是大表查询。”

这句话一出口,面试官眼睛一定会亮一下。

面试时,面试官继续追问我:

“那GROUP BY和DISTINCT呢?它们是不是也会拖慢速度?”

我立刻想到了之前的惨痛经历。那时候我写了一个统计SQL:

结果线上跑了半天,CPU打满。后来我才知道:

MySQL执行 GROUP BY 时默认会排序。如果数据量大,没索引,那就是灾难。

优化方案:

1、利用索引

给 student_id 建索引,MySQL能直接利用索引分组,大幅加速。

2、用DISTINCT时同理

SELECT DISTINCT student_id FROM score;如果有索引,DISTINCT直接走索引去重,效率嗖嗖的。

3、GROUP BY + ORDER BY NULL

如果你不关心结果的顺序,可以这样写:ORDER BY NULL 告诉MySQL:别再排序了,直接分组结果就行。这样能避免文件排序,大幅提速。

假设我们有学生表和成绩表,需要统计每个学生选课数。

原始写法:

这里用 s.name 分组其实很低效,因为 name 不是主键,还可能存在重复或者长字符串比较。

优化写法:

理由很简单:

主键/标识列更容易利用索引。字符串分组开销大,而数字分组快如闪电。

小米碎碎念:这一点,面试官经常会用来考察候选人是否理解“索引对分组的影响”。

有些小伙伴喜欢用 WITH ROLLUP 做超级聚合,比如统计成绩时自动加总:

虽然语法很酷,但问题是:

ROLLUP 计算量大,容易让查询变慢。有些逻辑其实在应用层做更灵活,比如用Java/Go/Python聚合。

所以,面试官要是问到这里,我一般会说:

“在数据量不大时,ROLLUP很方便。但如果是大数据量场景,建议把超级聚合逻辑挪到应用程序处理,数据库只负责最基本的统计。”

这句话能让你显得思路全面,不死抠SQL,而是懂得架构层面取舍。

我总结了一套面试时特别好用的“四步口诀”,分享给大家:

能JOIN就不用子查询:特别是 IN (SELECT …),替换成JOIN几乎必快。GROUP BY/DISTINCT走索引:一定要确认字段有索引,不然就是全表扫描。分组列优先用主键或整型标识列:避免用字符串或复杂字段做分组。ORDER BY NULL + 应用层聚合:不需要排序时,果断加 ORDER BY NULL;超级聚合挪到应用层。

只要这四步背下来,面试官再怎么追问,你都能侃侃而谈。

最后分享一个让我刻骨铭心的场景。那是我入职某电商平台的第一周,老板让我写个统计SQL:

结果跑了10分钟还没出来,老板差点以为我不会写SQL。后来我改成:

0.8秒出结果!老板看完还夸我一句:“小米,干得漂亮。”

从那以后,我就彻底记住了:

子查询能不用就别用,优化就是钱。”

如果你在面试中被问到“如何优化子查询?”,千万别慌。按照我上面分享的思路来:

先说子查询的缺点(执行慢、索引利用率低、容易临时表)。再一条条抛出优化思路(JOIN替代、GROUP BY优化、标识列分组、ORDER BY NULL、ROLLUP挪应用层)。最后补充一点自己的实战经验。

这样下来,不仅能显得你技术扎实,还能让面试官觉得你是“踩过坑、能解决问题”的人。

毕竟,面试官要找的不是会背八股的人,而是能把问题搞定的工程师。

我是小米,一个还在努力成长的程序员。希望今天这篇文章能帮你在面试里多拿几分,也能在工作中少踩几个坑。

如果你觉得文章有用,记得点个“赞”和“在看”,我们下次再见!

来源:鸿灿教育

相关推荐