SQL 优化那些事:面试官为什么总爱问这些?
前言
无论是在后端面试,还是数据库岗位,甚至全栈岗位,SQL 优化永远是绕不开的一道题。为什么面试官对这个乐此不疲?其实,SQL 查询性能的好坏,直接关系到系统稳定性、用户体验和服务器成本。
这篇文章就来聊聊:面试官到底为什么总爱问这些?以及我们该怎么准备。
一、面试官为什么爱问 SQL 优化?
📌 1. 和项目实战强相关
大部分系统后端最终都会落到数据库,SQL 写得烂,直接搞崩服务器。
📌 2. 能看出候选人系统性思维
考察你是否只会 CRUD,还是懂得分析执行计划、优化索引、调优查询方式。
📌 3. 高频场景,容易出坑
像联表、分页、大数据量、慢查询,这些日常开发就容易踩坑。
二、SQL 优化常见考点汇总 + 示例 SQL
📌 1️⃣ 慢查询排查流程
📍 查询当前执行的 SQL
SHOW PROCESSLIST;
📍 查看执行计划
EXPLAIN SELECT id, name FROM users WHERE age > 30;
返回结果重点看:
- type(访问类型,越靠近 ALL 性能越差)
- possible_keys / key
- rows
- Extra(如 Using filesort、Using temporary)
📌 2️⃣ 索引相关考点
📍 创建联合索引
CREATE INDEX idx_name_age ON users(name, age);
📍 最左前缀原则命中 ✅
SELECT * FROM users WHERE name = 'Tom';
📍 索引失效 ❌(like 前置%、函数包裹)
-- 索引失效例子
SELECT * FROM users WHERE name LIKE '%Tom%'; -- 前置百分号
SELECT * FROM users WHERE DATE(created_at) = '2024-05-01'; -- 函数包裹
📍 避免隐式类型转换
-- 假设 phone 字段是 varchar,以下会导致索引失效
SELECT * FROM users WHERE phone = 13800001111;
-- 应改为
SELECT * FROM users WHERE phone = '13800001111';
📌 3️⃣ SQL 写法优化
📍 避免 SELECT *,指定字段
SELECT id, name, age FROM users WHERE age > 30;
📍 IN vs EXISTS
-- IN 用于小结果集
SELECT * FROM users WHERE id IN (SELECT user_id FROM orders WHERE amount > 100);
-- EXISTS 更适合大表子查询
SELECT * FROM users u WHERE EXISTS (
SELECT 1 FROM orders o WHERE o.user_id = u.id AND o.amount > 100
);
📍 分页优化(大 offset 替代方案)
-- 慢:offset 大时性能差
SELECT * FROM orders ORDER BY id LIMIT 100000, 10;
-- 优化:记录上次最大 id,基于索引分页
SELECT * FROM orders WHERE id > 500000 ORDER BY id LIMIT 10;
📌 4️⃣ 表结构设计对性能的影响
📍 数据类型合理选择
- 小整数用 TINYINT、SMALLINT
- 金额类用 DECIMAL(10,2)
📍 字段是否允许 NULL
- 经常查询的字段尽量 NOT NULL,可减少存储空间和判断成本。
三、典型面试题盘点
📌 面试题 1:如何排查一条 SQL 慢查询?
- 通过慢查询日志或 SHOW PROCESSLIST 定位慢 SQL
- 使用 EXPLAIN 查看执行计划,分析 type、rows、Extra 等字段
- 检查是否走索引,是否存在 Using filesort、Using temporary
- 调整 SQL 写法或增加索引
- 必要时调整表结构或分库分表
📌 面试题 2:哪些情况会导致索引失效?
- 使用 LIKE ‘%xxx’ 前置百分号
- 对索引字段进行函数或运算处理
- 查询条件类型不一致,发生隐式类型转换
- 联合索引查询时不满足最左前缀原则
- 使用 OR 条件,某个分支未命中索引
- 索引字段参与表达式计算
📌 面试题 3:百万级数据分页如何优化?
- 避免使用 OFFSET + LIMIT,越往后越慢
- 改为基于索引或主键方式分页:记录上一页最大 id,下一页从该 id 往后查
- 或者使用覆盖索引 + 子查询方式
📌 面试题 4:IN 和 EXISTS 的区别,哪个性能更好?
- IN:先执行子查询,生成结果集,再在主表中匹配,适合小结果集
- EXISTS:主表每行逐一验证子查询是否存在,适合子查询大表
- 实际执行看执行计划,数据量不同时优劣不同
- 建议面试时说:“视表大小和执行计划而定,通常小表用 IN,大表用 EXISTS”
📌 面试题 5:什么是覆盖索引 (covering index)?
- 查询的字段全部在索引中,无需回表,从索引直接返回结果
- 能极大提高查询效率
- 查看 EXPLAIN 中 Extra 字段显示 Using index
📌 面试题 6:ORDER BY 性能问题如何优化?
- ORDER BY 会导致 Using filesort,尤其分页时更慢
优化方法:
给排序字段建立索引
限制返回行数(LIMIT)
尽量避免多列排序和大数据量排序
使用覆盖索引提升效率
📌 面试题 7:联合索引和多个单列索引有什么区别?
- 联合索引:一个索引包含多个字段,按顺序排序,满足最左前缀原则
- 单列索引:每个字段单独一个索引
- 联合索引查询效率高,能减少回表次数
- 多个单列索引多靠索引合并,效率相对差
面试答 SQL 优化题,结尾别忘记顺手加一句:实际项目里,我通常会通过 EXPLAIN 和慢查询日志定位,再根据具体情况选择索引调整、SQL 改写或者表结构优化。
总结
- **面试前至少掌握慢查询排查、索引优化、SQL 写法优化这三块。
- 多用 EXPLAIN 养成良好写 SQL 的习惯。
- 项目里碰到慢 SQL,千万别甩锅 DBA,先自查。**