Files
zhuangang/topics/backend/mongodb/interview.md
T

3.9 KiB
Raw Blame History

id, title, type, domain, stack, tags, level, related, week
id title type domain stack tags level related week
backend.mongodb.interview MongoDB 面试题 interview backend
mongodb
MongoDB
文档模型
索引
事务
面试
basic
backend.mongodb.document-model
14
16

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 或内存排序;检查是否新增了查询条件导致索引不匹配、数据分布变化、索引过多影响写入;修复后对比执行统计。

追问:建索引会影响线上吗?→ 会占用资源,选择低峰期建立,大集合关注构建进度和副本同步延迟。