Skip to content

数据库面试题

MySQL

1. 索引的底层数据结构是什么?为什么用 B+Tree?

MySQL InnoDB 引擎使用 B+Tree 作为索引结构。

为什么用 B+Tree?

  • 相比二叉树,B+Tree 是多路搜索树,高度更低,减少磁盘 IO
  • 相比 B-Tree,B+Tree 非叶子节点只存索引,单节点存储更多索引,降低树高
  • 叶子节点形成有序链表,支持范围查询
  • 所有数据存储在叶子节点,查询效率稳定

2. 聚簇索引和非聚簇索引的区别?

类型聚簇索引非聚簇索引
叶子节点存储完整行数据主键值
数量限制一个表只能有一个可以有多个
是否需要回表不需要可能需要
默认创建主键自动创建手动创建

3. 什么是回表?如何避免?

回表:通过非聚簇索引查询时,先查到主键值,再通过主键去聚簇索引查找完整数据的过程。

避免方法:使用覆盖索引,即查询的列都在索引中,无需回表。

sql
-- 假设建立了 (name, age) 联合索引
SELECT name, age FROM user WHERE name = '张三';  -- 覆盖索引,无需回表
SELECT * FROM user WHERE name = '张三';           -- 需要回表

4. MySQL 事务隔离级别有哪些?

隔离级别脏读不可重复读幻读
READ UNCOMMITTED
READ COMMITTED不会
REPEATABLE READ(默认)不会不会会(部分解决)
SERIALIZABLE不会不会不会

InnoDB 的 REPEATABLE READ 通过 MVCC + Next-Key Lock 基本解决了幻读。

5. 慢查询如何优化?

  1. 开启慢查询日志,定位慢 SQL
  2. 使用 EXPLAIN 分析执行计划,重点关注 type、rows、Extra
  3. 检查是否命中索引,必要时添加索引
  4. 避免 SELECT *,返回必要字段
  5. 优化分页(深分页用子查询或游标)
  6. 大表考虑分库分表

Redis

6. Redis 为什么这么快?

  • 纯内存操作:数据存储在内存中
  • 单线程模型:避免上下文切换和锁竞争(Redis 6.0 后引入多线程 IO)
  • IO 多路复用:epoll 模型处理高并发连接
  • 高效的数据结构:SDS、压缩列表、跳表等

7. 如何保证缓存与数据库的一致性?

  • Cache Aside 模式:先更新数据库,再删除缓存
  • 延迟双删:先删缓存 → 更新数据库 → 延迟再删缓存
  • 读写锁:写操作加锁,读操作无锁
  • 最终一致性方案:使用 Canal 监听 binlog 异步更新缓存