3.9 KiB
id, title, type, domain, stack, tags, level, related, week
| id | title | type | domain | stack | tags | level | related | week | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| backend.mongodb.interview | MongoDB 面试题 | interview | backend |
|
|
basic |
|
|
MongoDB 面试题
基础
【基础】MongoDB 和 MySQL / PostgreSQL 怎么选?
参考答案:结构多变、以文档为单位读写、写入量大、可以接受反范式的数据(日志、对话、内容、配置)适合 MongoDB;强一致事务、复杂关联查询和报表(订单、账务)更适合关系型。很多系统组合使用。
追问:PostgreSQL 的 JSONB 能不能代替?→ 中小规模、需要和关系数据一起做事务时完全可以;数据量大、结构差异大、需要水平分片时 MongoDB 更自然。
【基础】嵌入和引用怎么选?
参考答案:一起读写、数量有上限、不被单独访问的子数据嵌入;数量无上限、被多处共享或独立访问的数据引用。要考虑 16MB 单文档上限。
追问:订单里的商品信息嵌入还是引用?→ 嵌入下单时的快照(价格、名称),同时保留商品 id 引用,因为订单要记录成交时的状态。
【基础】MongoDB 支持事务吗?
参考答案:单文档操作天然原子;4.0 起支持副本集上的多文档事务,4.2 起支持分片集群。事务有性能开销和时间限制,优先通过建模减少对多文档事务的依赖。
追问:单机能用事务吗?→ 不能,需要副本集,开发环境可以启动单节点副本集。
进阶
【进阶】复合索引怎么设计?
参考答案:按 ESR 规则:等值字段在前、排序字段中间、范围字段在后;考虑选择性和查询覆盖;用 explain 验证是否走索引、是否有内存排序。
追问:为什么范围字段放在排序字段之前会有问题?→ 范围扫描后的结果在排序字段上不再有序,需要额外的内存排序。
【进阶】深分页怎么优化?
参考答案:避免大 skip(需要扫描并丢弃前面的文档),改用基于游标的分页:记录上一页最后一条的排序字段值(加 _id 打破平局),下一页查询“小于这个值”的数据。
追问:这种分页的缺点?→ 不能直接跳到第 N 页,适合无限滚动和“下一页”场景。
【进阶】变更流有什么用?怎么保证不丢事件?
参考答案:订阅数据变更,用于同步到搜索引擎、缓存、消息队列、审计。消费者处理完后保存 resume token,重启时从 token 继续;消费端做幂等;注意 oplog 保留窗口,停太久 token 会失效,需要全量重建。
追问:和 PostgreSQL 的什么机制类似?→ 逻辑复制 / CDC(如 Debezium 读取 WAL),以及 outbox 模式。
场景题
【场景题】AI 客服的对话记录怎么存储?
参考答案:会话文档嵌入最近消息,完整消息单独集合并以 conversation_id + seq 唯一索引保证顺序和幂等;带 tenant_id 做隔离;按 ESR 建列表索引;变更流同步 ES 做检索;按保留期归档。详见会话存储场景。
追问:如何防止越权查询?→ 数据访问层统一注入 tenant_id 条件,并有测试覆盖“缺少租户条件时拒绝执行”。
【场景题】线上一个查询突然变慢,你怎么排查?
参考答案:开启慢查询分析(profiler 或日志),对慢查询执行 explain("executionStats") 看扫描的文档数与返回数之比、是否 COLLSCAN 或内存排序;检查是否新增了查询条件导致索引不匹配、数据分布变化、索引过多影响写入;修复后对比执行统计。
追问:建索引会影响线上吗?→ 会占用资源,选择低峰期建立,大集合关注构建进度和副本同步延迟。