第4章 数据库与SQL优化面试题:索引优化、查询计划、分库分表、高频问题与公司侧重点

大厂高频考察点:B+树原理、EXPLAIN分析、分片策略与分布式查询优化。本章提供3个核心问答卡片+1个项目案例模板,覆盖从单机索引优化到分布式分库分表的完整链路。
慢查询如何优化? 确认索引类型 EXPLAIN分析 覆盖索引 / 回表 最左前缀 / 排序优化 B+Tree / Hash 场景 type/rows/Extra 关键字 Using index 避免回表 联合索引顺序 + filesort ✅ 选择高效索引 + SQL改写 → 性能提升

面试问答卡片

Q1:请解释B+树索引与哈希索引的区别,在什么场景下使用?

面试官考察点基础原理理解、索引适用场景、MySQL引擎差异
回答框架存储结构 → 查询能力 → 适用场景(Mem vs InnoDB)→ 回表/覆盖索引影响
示例回答B+树非叶子节点只存键,支持范围查询、排序、顺序IO;哈希索引仅等值查询且无法排序。InnoDB默认B+树适合OLTP;Memory引擎可选哈希索引适合高频等值查询。哈希索引有哈希碰撞和全表扫描风险。
可能追问为什么InnoDB选择B+树而非B树?B+树如何解决IO次数问题?
避坑提醒不要只说“哈希更快”,要强调范围查询场景;注意MyISAM和InnoDB索引实现差异。

Q2:如何分析一个慢查询?请描述完整步骤。

面试官考察点慢查询定位能力、EXPLAIN使用熟练度、SQL调优思路
回答框架开启慢日志 → 获取SQL → EXPLAIN分析(type/key/rows/Extra)→ 索引或SQL改写 → 测试验证 → 线上观察
示例回答先set global slow_query_log=ON,从慢日志取出SQL;执行EXPLAIN,若type=ALL且rows>10万则需加索引。关注Extra中的Using filesort或Using temporary,通过联合索引或改写JOIN消除。修改后explain验证rows减少。
可能追问Explain中type从好到坏的排序?Extra中Using index和Using index condition区别?
避坑提醒不要只提“加索引”,要具体说加什么索引(单列/联合)、顺序;优化后要回查慢日志确认效果。

Q3:在高并发场景下,你们是如何做分库分表的?有什么经验?

面试官考察点分布式设计能力、分片策略、全局ID、跨库查询解决方案
回答框架分片策略选择 → 分片键确定 → 全局ID生成 → 中间件选型 → 跨库查询处理 → 数据迁移方案
示例回答按用户ID哈希分16库每库256表,使用雪花ID保证全局唯一且趋势递增,用ShardingSphere-JDBC透明路由。跨库查询通过汇总表或ES二次聚合实现;分页排序采用基于有序ID的游标方式避免全量扫描。
可能追问分片后如何做跨库JOIN?数据倾斜怎么处理?分片键选择原则?
避坑提醒不要只夸分库分表好处,要主动提带来的复杂度(分布式事务、数据一致性、扩容问题);强调业务优先选择高频查询的分片键。

项目案例:电商订单系统读写分离与分库分表改造

Situation 订单量暴增10倍 单库MySQL瓶颈 Task 设计分库分表方案 保证高可用与扩展 Action ShardingSphere-JDBC 用户ID哈希分16库 Result QPS提升10倍+ 响应时间降低90% Takeaway:分片键选择最关键,避免跨库关联查询 全局唯一ID:雪花算法 数据迁移:双写+验证+切流
项目名称电商订单系统读写分离与分库分表改造
业务背景日订单量从10万增长至500万,MySQL单库写入性能骤降,慢查询比例超过20%
规模指标日订单500万+,订单表数据量2亿+;QPS峰值1.5万,读多写少(8:2)
技术栈MySQL 8.0 + ShardingSphere-JDBC + Redis + RocketMQ + Ruby on Rails(Ruby 3.0)
核心难点
  • 分片键选择:按订单ID vs 用户ID(最终选用户ID保证同用户数据聚合)
  • 跨分片排序分页:采用基于有序ID的游标方式,避免全量扫描
  • 全局唯一ID:使用雪花算法(workerId取自服务实例IP)
  • 分布式事务:最终一致性方案,通过RocketMQ + 本地事务表保证
面试高频追问
  • 如何保证分片后全局ID不重复且趋势递增?
  • 跨库分页时怎么处理性能问题?
  • 数据迁移怎样做到不停机平滑切换?
  • 分片后哈希冲突导致数据倾斜如何处理?
可迁移回答话术“核心思路是选择业务高频查询字段作为分片键,例如用户ID,确保大多数查询落在同一分片;对跨分片操作采用汇总表或Elasticsearch二次聚合;全局ID使用雪花算法保持趋势递增;分页通过游标(last_id)避免offset;数据迁移采用双写模式,在低峰期验证一致性后切流。” 此话术可迁移至任何分库分表类项目
💡 面试官侧重点:大厂(字节、阿里、腾讯)格外关注分布式场景下的分片键选择与跨库查询优化,建议结合具体业务数据量(如亿级)阐述。Ruby技术栈项目中,常通过ShardingSphere-JDBC或MySQL Router实现透明分片。