1)MySQL
设计一套由浅入深、层层递进的问题,不仅考察其基础知识,还能探查其实际经验、思考深度和系统设计能力。
🌱 第 1 题(基础认知):
你能简单说一下,MySQL 的分库分表是为了解决什么问题吗?
👉 意图:
- 判断是否知道为什么要分库分表;
- 看 TA 是不是仅仅知道“术语”,还是理解其背后的意义(如:数据量大、单表性能下降、查询慢、写入压力等)。
✅ 预期回答方向 & ⭐ 加分点 & ❌ 减分项/风险点
分库分表主要是为了解决单表或单库在数据量和并发访问量增加时带来的性能问题。通常分库分表是为了解决高并发、高数据量、性能瓶颈这类问题。
- ✅ 预期回答方向:
- 数据量大 → 单表性能瓶颈;
- IOPS / 连接数瓶颈;
- 提高查询/写入并发能力;
- 避免单点压力。
- ⭐ 加分点:
- 提到水平/垂直分库的区别;
- 水平分库:把同个表的数据按照一定规则分到不同的数据库中,数据库在不同的服务器上。好处:是多个数据库,降低了系统的 IO 和 CPU 压力。原则是选择合适的分片键和分片策略,和业务场景配合;避免数据热点和访问不均衡、避免二次扩容难度大
- 垂直分库:根据业务将表分类放到不同的数据库服务器上,好处是避免表之间竞争同个物理机的资源,比如 CPU/内存/硬盘/网络 IO,原则是根据业务相关性进行划分,领域模型,微服务划分一般就是垂直分库。
- 垂直分表: 将一个表字段拆分成多个表,每个表存储部分字段「分离热点字段和非热点字段」。(原则是业务经常组合查询的字段一个表;不常用字段一个表)。
- 水平分表:同个数据库内,把一个表的数据按照一定规则拆分到多个表中,对数据进行拆分,不影响表结构。好处是单个表的数据量少了,业务 SQL 执行效率高,降低了系统的 IO 和 CPU 压力。原则是选择合适的分片键和分片策略,和业务场景配合;避免数据热点和访问不均衡、避免二次扩容难度大。
- 理解是数据库扩展性设计的一部分;
- TODO
- 能结合业务场景描述,如订单、日志等。
- TODO
- 提到水平/垂直分库的区别;
- ❌ 减分项:
- 不清楚为什么要分;
- 把分库分表当成默认选项,而不是按需设计;
- 用词模糊、不成体系。
🌿 第 2 题(常规实践):
你在过去的项目中,有使用过哪些分库分表的策略?你是如何选择这些策略的?
👉 意图:
- 考察是否有实际经验;
- 是否了解常见的分库(按功能、按范围、按 hash)、分表(时间维度、ID 取模)等策略;
- 是否考虑了业务的特征、读写模式等因素。
✅ 预期回答方向 & ⭐ 加分点 & ❌ 减分项/风险点
在一个电商订单系统中,我们使用了 按业务分库 + 按用户 ID 取模分表 的方案。
- 分库:订单与用户信息分库,用户库和订单库分布在不同的 MySQL 实例上,以减少单库压力;
- 分表:订单表使用用户 ID 取模分为 16 张表,原因是用户 ID 是请求中最常见的过滤条件,取模后分布比较均匀,查询路由简单;
在这个过程中,我们使用了 ShardingSphere 来做 SQL 路由、分库分表中间件,可以避免自己手写逻辑,并支持未来扩容。
同时,我们也设计了 预留表(如 32 张,但只启用 16 张),后期可以按需扩容。
✅ 预期回答方向:
- 明确说出按业务分库、按时间/ID 分表等;
- 能解释选择的理由;
- 提到是否使用中间件。
- Apache ShardingSphere 是一款分布式的数据库生态系统,可以将任意数据库转换为分布式数据库,并通过数据分片、弹性伸缩、加密等能力对原有数据库进行增强。
⭐ 加分点:
- 有动态扩容设计;
- TODO
- 避免数据倾斜;
- TODO
- 提到一致性、路由算法等细节。
- TODO
- 有动态扩容设计;
❌ 减分项:
- 策略选择不合逻辑(如每天的数据量很小也用了 hash 分表);
- 完全依赖框架,无法说清原理。
🌳 第 3 题(性能调优基础):
假设你发现一个表的查询速度变慢了,你一般会从哪些方面进行排查和优化?
👉 意图:
- 评估是否掌握基本的性能调优方法;
- 应包括:慢查询日志、索引设计、SQL 语句分析、执行计划 EXPLAIN、表结构设计等。
✅ 预期回答方向 & ⭐ 加分点 & ❌ 减分项/风险点
✅ 预期回答方向:
- 查看慢查询日志;
- 使用
EXPLAIN
分析执行计划; - 查看索引、SQL 语法;
- 数据量/分页/网络层因素等。
⭐ 加分点:
- 提到
show processlist
、information_schema
表等; - 涉及合理索引设计(联合索引、覆盖索引);
- 使用业务维度说优化背景。
- 提到
❌ 减分项:
- 优化仅限于“加索引”,缺乏系统性;
- 无法定位是 SQL 问题还是索引、表结构问题。
📝 标准参考答案: 我一般按以下步骤来排查查询变慢的问题:
- 查看慢查询日志:定位慢 SQL;
- 使用
EXPLAIN
分析执行计划,判断是否走了全表扫描、使用了合适的索引;- 确认索引是否生效,是否为“最左前缀”、是否命中了查询字段;
- 检查是否存在 回表、临时表、filesort 操作,尤其是分页时;
- 考察 SQL 写法是否合理(避免
SELECT *
、子查询是否可以改为 JOIN);- 数据层面看是否存在数据倾斜、大字段过多、频繁更新等问题;
- 硬件层面也可能导致瓶颈,如磁盘 IOPS 饱和;
实际案例中,我曾优化一条
WHERE user_id = ? ORDER BY create_time DESC LIMIT 100
的语句,通过添加(user_id, create_time)
的联合索引,将查询时间从 1.2s 降到了 30ms。
🌲 第 4 题(深入优化):
你有没有遇到过分表后查询性能变差的情况?你是如何处理跨表/跨库查询带来的性能问题的?
👉 意图:
- 判断是否有深度处理经验;
- 观察其对跨表 join 代价、数据聚合、分页、事务一致性、分布式事务问题的认知;
- 是否使用中间层(如:MyCat、ShardingSphere、自研中间件)优化过。
✅ 预期回答方向 & ⭐ 加分点 & ❌ 减分项/风险点
✅ 预期回答方向:
- 表示遇到过问题;
- 提到跨表 JOIN 的不可行性;
- 随着表越多,表中的数据量越多,JOIN 的效率会呈指数级下降。
- 有合适的折中方案(预聚合、异步汇总、分库路由等)。
⭐ 加分点:
- 引入缓存;
- 使用并行查询合并;
- 善于使用中间件优化,比如 ShardingSphere 的广播表等。
❌ 减分项:
- 认为分库分表之后查询性能一定提升;
- 不知道如何解决 join 不可用问题。
📝 标准参考答案:
是的,分表后我们确实遇到过查询变慢的问题,尤其是涉及跨表聚合统计的场景。
因为一条统计 SQL 需要访问多个分表,甚至多个数据库,这会导致查询时间变长,还会因为网络调用延迟增加 RT。
我们的解决方案有几种:
- 对于实时性要求不高的聚合统计,使用定时任务 + 聚合表(异步归集);
- 对于常用的分页查询,通过逻辑分片 + 多线程查询合并结果;
- 对于必须 JOIN 的表(如用户信息),我们用了一种“广播表策略”,把小表同步到每个库,避免 join 出现性能瓶颈;
- 另外,一些全局查询,直接走 ElasticSearch 做二级索引和分析;
此外,我们也会在中间层进行 query rewrite,避免业务直接访问多个分表。
🪵 第 5 题(系统设计层面):
如果现在有一个用户订单表,未来预计每天新增 1000 万条数据,你会如何设计这个表的分库分表方案,以及未来的扩展性怎么考虑?
👉 意图:
- 考察系统设计能力;
- 是否具备前瞻性思维;
- 看其是否考虑了:主键生成策略(如雪花 ID)、分区设计、冷热数据分离、数据归档、分库分表中间件的选择、在线扩容策略等。
✅ 预期回答方向 & ⭐ 加分点 & ❌ 减分项/风险点
✅ 预期回答方向:
- 主动规划数据增长;
- 分库+分表设计;
- 可扩展性、数据归档、冷热数据、主键策略等考虑周全。
⭐ 加分点:
- 设计了“按月分表 + 动态建表 + 统一路由中间件”;
- 主键使用分布式 ID(如雪花算法);
- 数据归档策略明确;
- 提到限流、缓存等手段缓解写入压力。
❌ 减分项:
- 一开始就定死库表数量;
- 使用自增 ID 导致跨库主键冲突;
- 设计不能支持后续扩容。
📝 标准参考答案:
如果预计每天新增订单数据在千万级别,我会这样设计订单表:
分表策略:按时间维度(如“月”)进行分表,例如:
order_202504
、order_202505
;每张表只保存一个月数据,避免单表过大;分库策略:根据用户 ID 或订单 ID 对 2-4 个库进行水平拆分,防止单库成为瓶颈;
主键设计:使用雪花算法(或 UUID、Mongo ObjectId)生成全局唯一 ID,避免分布式主键冲突;
中间件:使用 ShardingSphere 或自研中间件,处理路由、执行计划、SQL rewrite;
数据归档策略:针对 3 个月以上订单数据归档到独立存储系统(如归档库、冷数据存储或对象存储);
扩容预留:分库分表采用配置化 + 动态扩容机制,支持后续按季度新增表;
缓存设计:高频订单数据进入 Redis 做缓存,减少查询压力;
最后,整体方案要考虑“高并发写入 + 查询灵活性 + 长期维护成本”的平衡。