第4章 数据库性能调优面试题:SQL优化、索引设计、分库分表、读写分离高频问答
面试问答卡片
📌 问题1:一条慢SQL怎么排查和优化?
面试官考察点:是否掌握排查工具、优化思路、执行计划分析。
回答框架:1)使用 EXPLAIN 查看执行计划(type、rows、Extra);2)检查是否走全表扫描,分析索引使用情况;3)根据索引覆盖、减少回表、避免 SELECT *、限制扫描行数等优化。
示例回答:先用 EXPLAIN 发现该查询 type = ALL,无索引。检查关联字段后发现 where 条件列未建立索引,为支付流水号加唯一索引后 type 变为 ref,响应从 2s 降到 10ms。
可能追问:filesort 如何优化?联合索引最左前缀失效场景?Using temporary 怎么解决?
📌 问题2:支付流水表每天几千万数据,怎么设计索引?
面试官考察点:联合索引设计、索引选择性、避免索引失效。
回答框架:1)确定高频查询条件(商户ID、交易时间、订单状态);2)建立联合索引(商户ID + 交易时间 + 状态);3)考虑覆盖索引减少回表;4)定期清理历史数据或归档。
示例回答:支付流水表核心查询是“按商户查当天订单”。建联合索引 (merchant_id, create_time),状态字段选择性低不适合单独做索引,但可作为右缀加入。对于超大表配合分区分表。
可能追问:为什么状态字段不适合单独索引?IN 查询会走索引吗?order by 和索引顺序的关系?
DATE())导致失效。📌 问题3:什么场景下需要做分库分表?读写分离怎么实现?
面试官考察点:架构演进能力、分片策略、主从延迟处理。
回答框架:1)单表数据超千万且索引无法满足;2)分片键选择业务相关字段(如用户ID、商户ID);3)读写分离通过主库写、从库读,中间件配置(如 ShardingSphere、MyCat);4)解决主从延迟:强制读主、延迟阈值、缓存补偿。
示例回答:支付流水表日均500万行,单表超1亿后写入并发受限。采用商户ID取模分8库,每库再按月分表。读写分离:写操作走主库,读操作走从库,对实时性要求高的查询强制走主库。
可能追问:分库后跨库查询怎么处理?全局ID生成?分库分表后如何扩容?
项目案例实战模板
🚀 项目名称:支付结算系统流水库性能优化
| 业务背景 | 每日订单量超2000万,高峰QPS 5万,数据库成为瓶颈,订单查询超时严重。 |
| 规模指标 | 单表数据量超3亿行;写入TPS 8000;读延迟P99 > 2s;MySQL 8.0 单机。 |
| 技术栈 | MySQL 8.0 + MyBatis + ShardingSphere 5.x + Redis 缓存 + Canal 同步。 |
| 核心难点 | ① 分片键选商户ID导致热点商户单库压力大;② 按日分区后跨月查询性能差;③ 主从延迟30秒导致对账数据不一致。 |
面试高频追问:
- 热点商户怎么解决?(商户ID+时间字段二次分片,或单独缓存热数据)
- 跨月/跨年查询怎么做?(使用ES或ClickHouse做聚合查询,MySQL只保留近期数据)
- 主从延迟怎么保证对账准确性?(对账采用双主库 + 最终一致性校验 + 离线补偿)
- 分库后分布式事务怎么处理?(使用本地消息表 + 定时任务补偿,避免强XA)
- 扩容时怎么不停机迁移?(双写 + 增量同步 + 灰度切流)
可迁移回答话术:
“在支付场景中,我们优先通过索引优化和读写分离满足业务增长,当单表数据量超过1亿且索引无法支撑时,才引入分库分表。分片键选择业务稳定性最高的商户ID,并配合二级时间字段避免数据倾斜。针对热点问题,通过缓存和异步分流来缓解,不盲目增加分片数。”