您现在的位置是:烟消火灭网 > 焦点
数据库性能测试慢查询sql笔试题
烟消火灭网2026-10-17 07:45:45【焦点】3人已围观
简介我见过太多候选人栽在慢查询题上。不是不会写SQL,是压根没意识到面试官在考什么。 上周帮朋友复盘一场后端面试,题目很朴素:一张订单表五千万行,查某个用户最近一笔订单。他写了 SELECT * FROM
我见过太多候选人栽在慢查询题上。数据试慢试题不是库性不会写SQL,是查询压根没意识到面试官在考什么。
上周帮朋友复盘一场后端面试,数据试慢试题题目很朴素:一张订单表五千万行,库性查某个用户最近一笔订单。查询他写了 SELECT * FROM orders WHERE user_id = 123 ORDER BY created_at DESC LIMIT 1,数据试慢试题面试官点点头,库性接着问:这条SQL在线上跑,查询你觉得要多久?数据试慢试题他答“应该很快吧,有索引”。库性面试官笑了。查询
问题出在哪?数据试慢试题user_id 上确实有索引,但 created_at 没有。库性MySQL 拿着 user_id 索引捞出这个用户所有订单,查询可能是几百条,也可能是几十万条——取决于用户活跃度。然后全部回表,再排序,再取第一条。一个五年老用户,这个查询能跑三秒以上。线上并发一上来,CPU直接打满。
面试官真正想看的是什么
不是你能不能写出“能跑”的SQL,而是你能不能写出“跑得快”的SQL。这两者之间的差距,就是性能测试的核心。
回到那道题。正确解法是建联合索引 (user_id, created_at DESC)。有了它,InnoDB 直接在索引里定位到 user_id 分区,created_at 已经有序,取第一条,回表一次。毫秒级。同样的查询,不同的索引设计,性能差距三个数量级。面试官要的就是你嘴里说出“联合索引”和“最左前缀”这几个字。
但光说不够。你得能证明。
EXPLAIN 只是起点
很多人背过 EXPLAIN 的字段含义,type、key、rows、Extra。面试时也能说出“type=ALL 是全表扫描,要避免”。但真实场景里,EXPLAIN 的 rows 估算值可能和实际差几十倍。MySQL 的统计信息不是实时的,索引基数会漂移。
我习惯在面试里追问一句:你怎么确认优化真的生效了?
靠谱的回答是打开 slow_query_log,设 long_query_time = 0.1,跑一遍业务SQL,看 Query_time 和 Rows_examined。更狠一点,用 SHOW PROFILE 或者 performance_schema 看每个阶段的耗时。Sending data 阶段特别长,说明回表次数太多;Sorting result 出现,说明索引没覆盖排序。
这些操作不需要背,但需要你真的在测试环境折腾过。面试官分辨得出“背的”和“做过的”。
一个真实案例的细节
去年帮一个电商团队看慢查询。他们有个查询:SELECT COUNT(*) FROM order_items WHERE order_id IN (SELECT id FROM orders WHERE status = 1 AND created_at > '2024-01-01')。开发觉得子查询先过滤 orders,再拿 id 去查 order_items,逻辑没问题。
实际执行时,MySQL 5.7 把子查询物化成临时表,orders 表两千万行,status=1 的占三成,created_at 过滤后还有两百万行。临时表写磁盘,然后 order_items 跟这个临时表做半连接。慢查询日志里这条SQL跑了十八秒。
改成 JOIN 之后,优化器选了 order_items 的 order_id 索引,驱动表变成过滤后的 orders 子集,嵌套循环回表。同样逻辑,一点二秒。索引没变,写法变了,执行计划天差地别。
这个案例我经常在面试里讲。候选人听完能接上话的,基本都懂优化器行为。接不上的,说明只停留在“加索引”的层面。
别忽略写入代价
有人一听到慢查询就疯狂加索引。联合索引、覆盖索引、前缀索引全上。读是快了,写入呢?每个额外索引都要在 INSERT/UPDATE/DELETE 时维护 B+ 树。一张订单表挂八个索引,插入性能掉一半。
面试里我会问:这个查询QPS多少?如果一天跑两次,加索引不值。如果每秒两千次,不加索引就是事故。性能测试不是孤立的,得看业务场景。脱离读写比例谈索引优化,都是耍流氓。
慢查询笔试题考的不是SQL语法。考的是你脑子里有没有一幅执行计划的图,知不知道数据怎么从磁盘到内存再到结果集。能画出这幅图的人,写出来的SQL不会差。
很赞哦!(513)






