SQL 优化那些事:面试官为什么总爱问这些?

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,先自查。**
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

全干engineer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值