Skip to main content
Documents
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

MongoDB FAQ

内容:基础、索引、事务、性能优化、复制集、分片、场景题,按照难度从初级到高级排列。

一、MongoDB 基础概念题

1. 什么是 MongoDB?它的主要特点是什么?

MongoDB 是一个开源、分布式、面向文档的 NoSQL 数据库,采用 BSON 格式存储数据。

核心特点:

  • 无模式(Schema-Free)
  • 文档模型(支持嵌套结构)
  • 高性能、高并发
  • 原生支持横向扩展(Sharding)
  • 自动故障转移(Replica Set)
  • 丰富查询(包括聚合、地理位置、全文索引)

2. MongoDB 的数据模型是什么?

MongoDB 使用 文档(Document) 作为最小存储单位,相当于关系型数据库的一行。

  • 文档 -> BSON
  • 集合(Collection) -> 表
  • 数据库(Database) -> 数据库

3. MongoDB 的 BSON 是什么?

BSON = Binary JSON

相比 JSON:

  • 支持更多数据类型(date、binary、decimal128)
  • 读取快
  • 有长度字段,可顺序扫描

二、索引

4. MongoDB 中有哪些类型的索引?

常见索引类型:

  • 单字段索引
  • 复合索引(Compound)
  • 唯一索引(unique)
  • TTL 索引
  • 哈希索引(Hashed)
  • 文本索引(Text)
  • 地理位置索引(2dsphere)

5. 什么是复合索引的“左前缀原则”?

如索引:

{ a: 1, b: 1, c: 1 }

可用于:

  • a
  • a + b
  • a + b + c

不能用于:

  • b
  • c
  • b + c

6. explain() 输出里的 COLLSCAN 是什么?

COLLSCAN = 全表扫描

表示没有走索引,是性能问题的最大根源。

7. 如何判断查询是否使用了索引?

使用:

db.collection.find({...}).explain("executionStats")

关注字段:

  • stage 是否包含 IXSCAN
  • totalDocsExamined 是否远小于 nReturned

8. MongoDB 多字段排序时必须有索引吗?

是的。

MongoDB 只能在 索引顺序完全匹配 的情况下进行排序。

三、事务 & 写入

9. MongoDB 支持事务吗?

支持。

从 MongoDB 4.0 开始支持 多文档 ACID 事务(Replica Set)

从 4.2 起支持 分片集群事务(Sharding)

10. MongoDB 事务性能与 MySQL 对比?

MongoDB 的事务性能更差,因为其文档模型原本就设计为减少事务场景。

MongoDB 事务适用于:

  • 多集合跨文档一致性
  • 金融级业务极少使用的场景

11. 什么是 upsert?

  • 如果不存在 -> 插入
  • 如果存在 -> 更新

相当于 MySQL 的:

insert ... on duplicate key update

12. 写入会触发 document move 是什么?

当文档大小变大时,需要移动到新的数据页,会导致:

  • 性能降低
  • 磁盘 I/O 增加
  • 复制集 oplog 增大

避免方法:

  • 不要频繁增加/减少文档字段
  • 大字段拆分子集合

四、性能优化

13. MongoDB 性能慢一般有哪些原因?

常见 TOP 原因:

  • 无索引 -> COLLSCAN(最常见)
  • 复合索引未命中
  • 查询返回字段过多(未使用投影)
  • 写入太频繁导致锁
  • 文档太大(>16MB 限制)
  • COUNT() 过慢
  • 事务长时间占用锁
  • 磁盘 I/O 高

14. 如何优化 MongoDB 分页?

不要使用:

skip + limit

因为 skip 需要扫描 N 条记录。

使用:

{_id: {$gt: last_id}}  // “游标分页”
limit 10

15. 如何提高批量写入性能?

使用:

bulkWrite()

而不是循环 insert。

16. MongoDB 为什么更适合读多写少业务?

因为 MongoDB 写入需要:

  • 写 journal
  • 写数据文件
  • 复制到副本集其他节点
  • 更新多个索引

写放大显著比 MySQL 大。

17. 什么时候需要使用 allowDiskUse?

当聚合管道需要大量内存:

db.col.aggregate([...], { allowDiskUse: true })

五、复制集(Replica Set)

18. MongoDB 复制集的选举过程是什么?

基于 Raft 类似机制。

选举条件:

  • 成员 ping 可达
  • 票数过半
  • 优先级优先(priority)
  • oplog 数据最新

19. PRIMARY 为什么会变 SECONDARY?

原因:

  • 网络不通
  • 心跳超时
  • 优先级低
  • oplog 追不上
  • 资源不足(内存/CPU 过高)

20. 什么是 oplog?作用是什么?

oplog(operation log)是 复制集的数据复制日志

SECONDARY 节点从 oplog 同步数据。

关键参数:

  • oplog 大小(要保证至少 24 小时窗口)
  • oplog 落后太久会导致需要全量复制

21. 复制集节点延迟如何查看?

rs.printSlaveReplicationInfo()

六、分片(Sharding)

22. MongoDB 为什么需要分片?

因为单个节点:

  • 内存有限
  • 磁盘有限
  • IOPS 不够
  • QPS 负载瓶颈

分片可横向扩容至无限容量。

23. 分片键应该如何选择?

最佳实践:

  • 高基数(high cardinality)
  • 写入均匀
  • 避免单调递增

推荐:

  • hashed(_id)
  • hashed(user_id)

24. 错误的分片键会导致什么问题?

典型问题:

  • 数据热点(所有写入集中到一个分片)
  • chunk 分裂/迁移速度慢
  • 节点负载不均衡

25. shard key 是否可以修改?

不能修改(几乎不可能)。

MongoDB 设计中 shard key 是永久性的。

七、安全

26. 如何启用 MongoDB 用户验证?

mongod.conf:

security:
  authorization: enabled

27. MongoDB 推荐使用什么认证方式?

SCRAM-SHA-256

比 SHA-1 更安全。

28. MongoDB 如何进行权限控制?

基于:

  • 用户(user)
  • 角色(role)
  • 数据库(db)

例如:

readWrite
dbAdmin
clusterAdmin
backup
restore

八、实战场景

29. 如果 MongoDB 的 CPU 100% 怎么排查?

排查思路:

  1. currentOp() 查看哪些查询在跑
  2. explain() 是否出现 COLLSCAN
  3. 看是否走了全文索引
  4. 观察 WiredTiger cache
  5. 观察是否大量 fetch 文档
  6. 看是否有大 $in 查询
  7. 是否有无索引的 $lookup
  8. 是否有长事务卡住锁

30. 如果 MongoDB 写入突然变慢怎么办?

可能原因:

  • 索引太多 -> 写入变慢
  • journal 写入慢(磁盘 I/O)
  • 文档过大
  • 分片平衡导致 chunk migrate 阻塞
  • 复制集延迟大
  • 主节点锁等待

排查:

  • db.serverStatus()
  • iostat
  • rs.printSlaveReplicationInfo()

31. MongoDB 集合非常大时如何提升性能?

策略:

  • 创建必要索引
  • 热点字段分片
  • 使用压缩
  • 不要查询大文档
  • 禁止 deep skip
  • 使用游标分页
  • 定期 archive 归档旧数据
  • 将大字段(如图片)拆分存储到 GridFS

32. 如何判断 MongoDB 分片是否 imbalance(不均衡)?

运行:

sh.status()

检查:

  • chunk 分布
  • 每个 shard 的数据量差异
  • balancer 是否运行

33. 如果 shard key 选错了怎么办?

解决方案:

  1. 新建一个新的 collection -> 正确 shard key
  2. 导入数据 -> 落新 collection
  3. 逐渐切换业务到新的 collection

MongoDB 不支持直接修改 shard key。

34. MongoDB 的文档模型有哪些反模式?

反例:

  • 文档太大
  • 太多嵌套结构
  • 数组无限增长
  • 单文档单字段过巨大(>16MB)
  • 子文档更新过多 -> document move

九、高级(架构师)

35. WiredTiger Cache 是什么?为什么重要?

WiredTiger Cache 控制 MongoDB 内存分配(50% 内存)。

作用:

  • 存放热数据
  • 存放索引
  • 读写缓存

Cache miss 会:

  • 触发磁盘 I/O
  • 性能急剧下降

36. MongoDB 中的锁是怎样的?

  • 文档级锁(写入锁单文档,不锁集合)
  • 全局锁(元数据操作)
  • 读写锁(Share/Exclusive)
  • 索引创建时可能全局锁

37. 如何处理热点写入问题?

解决方法:

  • hashed shard key
  • 拆分成多个集合(冷热分离)
  • 增加多个 mongos
  • 减少热点字段更新

38. MongoDB 如何保证数据一致性?

通过:

  • Write Concern
  • Read Concern
  • Multi-Document Transactions
  • Majority Quorum

39. 什么是 Write Concern?有哪些级别?

控制写入确认级别:

  • 0 fire-and-forget
  • 1 primary
  • majority(推荐)
  • w: <num> n 个节点确认

40. 如何做 MongoDB 备份恢复?

工具:

  • mongodump/mongorestore
  • mongoexport
  • 全量物理复制(LVM snapshot)
  • 复制集拉数据