2026大厂面试MySQL优化10问17认证网

正规官方授权
更专业・更权威

2026大厂面试MySQL优化10问

面试官最爱问什么?除了JVM和并发,MySQL优化绝对是出场率前三的考点。尤其2026年,大厂对数据库功底的要求越来越高——不仅要会写SQL,更要能说清为什么慢、怎么优化、原理是什么

这10道题是从近半年面经中提炼的高频题,题题都有标准答案。

1. 一条SQL执行很慢,怎么排查?

不直接答”加索引”,应该展示排查思路:

-- 第一步:开慢查询日志
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1;

-- 第二步:用EXPLAIN看执行计划
EXPLAIN SELECT * FROM orders WHERE user_id = 100 AND status = 'paid';

关键看 type(ALL最差→index→range→ref→const最好)、rows(扫描行数)、Extra(Using filesort/Using temporary都是坏信号)。然后用 SHOW PROFILE 看各阶段耗时,定位是IO瓶颈还是CPU瓶颈。

2. EXPLAIN结果里的type字段,哪些需要优化?

type 含义 是否要优化
ALL 全表扫描 ✅ 必须优化
index 全索引扫描 ⚠️ 数据量大时需优化
range 索引范围扫描 一般OK
ref 非唯一索引查找 ✅ 理想
eq_ref 唯一索引查找 ✅ 最优
const 主键等值 ✅ 完美

面试加分点: 提到 index 虽然比 ALL 好,但如果 Extra 列显示 Using index(覆盖索引),那就是最优情况——连回表都省了。

3. 索引建得越多越好吗?

恰恰相反。 三个代价:

  1. 写入性能下降:每插入/更新一行,所有索引都要维护,索引越多写入越慢
  2. 占用磁盘空间:索引本身是数据结构,一个表的索引可能比数据还大
  3. 优化器选择困难:索引太多,MySQL优化器可能选错索引

实践建议: 单表索引控制在5个以内。遵循”最左前缀”原则让一个联合索引覆盖多个查询场景。

4. 什么是覆盖索引?什么时候用?

覆盖索引是指查询的所有字段都在索引中,不需要回表查聚簇索引。

-- 建联合索引
CREATE INDEX idx_user_status_time ON orders(user_id, status, create_time);

-- 这个查询就是覆盖索引:SELECT的字段全在索引里
SELECT user_id, status, create_time 
FROM orders 
WHERE user_id = 100 AND status = 'paid';

EXPLAIN的Extra列会显示 Using index——不需要回表,性能最高。联合索引的列顺序很关键,必须把等值查询列放前面,范围查询列放后面。

5. 分库分表怎么选sharding key?

核心原则:让大多数查询落到单个分片上。

// 如果是电商订单表,user_id做sharding key
// 因为查"我的订单"是最高频场景
int shardId = userId.hashCode() % shardCount;

避免跨分片查询是关键。如果按 order_id 分片,查”我的订单”就要扫所有分片再聚合——这就是选错sharding key的典型后果。

面试加分: 提一嘴基因法——把用户ID编码进订单ID(如 order_id = userId后6位 + 时间戳 + 序列号),这样按订单查也能定位分片。

6. MySQL主从延迟怎么解决?

主从延迟本质是从库回放binlog的速度跟不上主库写入速度

排查三步走:

-- 查看延迟秒数
SHOW SLAVE STATUS\G  -- 看 Seconds_Behind_Master

解决方案(按严重程度递进): 1. 并行复制:MySQL 5.7+ 开启 slave_parallel_workers=4,按库并行回放 2. 半同步复制rpl_semi_sync_master_wait_for_slave_count=1,主库等至少1个从库确认 3. 拆分大事务:一个事务更新100万行→拆成10个10万行的事务 4. 读写分离兜底:关键业务强制读主库,非关键业务读从库

7. count(*) 和 count(1) 和 count(id) 哪个快?

答案是:几乎一样快。 在InnoDB中,count(*) 会选最小的二级索引来扫(因为二级索引比聚簇索引小),count(1) 和 count(id) 同理。MySQL 8.0优化器对 count(*) 做了专门优化,实际上 count(*) 就是最优写法

-- 三者性能相同,但count(*)语义最清晰,推荐
SELECT count(*) FROM orders WHERE status = 'paid';

真正影响性能的是WHERE条件有没有索引。没有索引,三种写法都是全表扫描。

8. 什么情况下索引会失效?

这道题面试官想听的不仅是列举,更要说明为什么失效

  1. LIKE以%开头 → 索引有序(B+树),前缀模糊无法定位起点
  2. 联合索引不满足最左前缀 → (a,b,c) 索引,查 b=1 用不上
  3. WHERE条件中对索引列做函数/运算 → WHERE YEAR(create_time)=2026,优化器无法用索引
  4. 类型隐式转换 → WHERE phone=13800138000,phone是varchar,MySQL把字符串转数字,索引失效
  5. OR条件中有一个列没索引 → WHERE a=1 OR b=2,b没索引→全表扫描

终极解决方案: OR改成UNION:

-- ❌ OR可能导致索引失效
SELECT * FROM t WHERE a = 1 OR b = 2;
-- ✅ UNION保证各自走索引
SELECT * FROM t WHERE a = 1 UNION SELECT * FROM t WHERE b = 2;

9. 大表加索引为什么不阻塞读写?Online DDL原理

MySQL 5.6+ 支持 Online DDL,加索引时不锁表。原理:

  1. 建立一个临时文件,记录DDL期间的数据变更(row log)
  2. 扫描原表数据,构建新索引
  3. 应用row log中的变更到新索引
  4. 原子切换新旧索引
-- ALGORITHM=INPLACE 不拷贝全表,LOCK=NONE 不锁表
ALTER TABLE orders ADD INDEX idx_status(status) ALGORITHM=INPLACE, LOCK=NONE;

⚠️ 坑: Online DDL需要额外的磁盘空间(约等于表大小),空间不足会失败。生产环境执行前先 df -h 确认空间。

10. 如何优化分页查询,特别是深分页?

-- ❌ 这种深分页:MySQL需要扫描前100010行,丢掉前100000行
SELECT * FROM orders ORDER BY id LIMIT 100000, 10;

方案一(最推荐):延迟关联

SELECT * FROM orders 
INNER JOIN (SELECT id FROM orders ORDER BY id LIMIT 100000, 10) AS tmp 
ON orders.id = tmp.id;

子查询只扫索引不回表,拿到10个id后再回表取完整数据。

方案二:游标分页

-- 记住上一页最后一条的id,下一页从这开始
SELECT * FROM orders WHERE id > 100000 ORDER BY id LIMIT 10;

面试加分点: 方案二不支持跳页,但ES和Twitter的Timeline都是这么干的——深分页本身就是个伪需求,用户不会翻到第1000页。


这10道题覆盖了索引、SQL优化、架构设计三个维度。面试时别只背答案,要在回答里展示排查思路——面试官最喜欢听”先看慢查询日志→EXPLAIN分析→看索引使用情况→考虑SQL改写”这种结构化思考。

如果这篇文章对你有帮助,转发给也在准备面试的朋友。

转自:云栖码客,作者:Java栈

版权申明:内容来源网络,版权归原创者所有,如有侵权请联系删除

想了解更多干货,可通过下方扫码关注

可扫码添加上智启元官方客服微信👇

未经允许不得转载:17认证网 » 2026大厂面试MySQL优化10问
分享到:0

评论已关闭。

400-663-6632
咨询老师
咨询老师
咨询老师