一、 MongoDB 核心概念解析

📄 文档与集合

MongoDB是文档型数据库,数据以BSON(Binary JSON)格式存储。与关系型数据库不同,MongoDB的集合(Collection)没有固定的表结构,允许同一集合中的文档拥有不同的字段。

{ "_id": ObjectId("507f1f77bcf86cd799439011"), "name": "张三", "age": 28, "skills": ["Java", "Python", "MongoDB"] }

🔍 索引机制

索引是提升查询性能的关键。MongoDB支持单字段索引、复合索引、多键索引、地理空间索引和文本索引。默认情况下,_id字段会自动创建唯一索引。

⚡ 面试题考点: 复合索引的顺序如何影响查询性能?

⚙️ 聚合框架

聚合管道(Aggregation Pipeline)是MongoDB强大的数据处理工具,支持分组、过滤、排序、投影等操作。它类似于Unix管道,数据经过多个阶段处理后输出结果。

db.orders.aggregate([ { $match: { status: "A" } }, { cust_id", total: { amount" } } } ])

二、 MongoDB 高频面试题详解

以下整理了面试官最常问的5个核心问题,涵盖原理、应用及实战场景。

Q1: 在什么情况下MongoDB索引会失效?

深度解析: 虽然MongoDB索引效率很高,但在某些查询模式下索引可能不被使用或效率低下。

  • 前缀匹配缺失: 对于复合索引 (A, B, C),如果查询条件只包含 B 或 C,而不包含 A,则索引可能无法有效利用(除非使用覆盖索引或特定优化)。
  • 正则表达式: 以 ^ 开头的正则表达式可以使用索引,但其他形式的正则表达式通常会导致全表扫描。
  • 类型不匹配: 查询值的类型与索引字段类型不一致时,索引可能失效。例如,用字符串 "123" 查询数字类型的字段。
  • 隐式类型转换: 在查询中使用运算或函数处理字段值时,如 db.col.find({ age: { $gt: 18 } }) 中若对 age 进行计算,索引可能失效。
// 索引失效示例 db.users.find({ where 通常不使用索引 // 正确示例 db.users.find({ age: { $gt: 18 } }); // 使用索引

Q2: 聚合框架和 MapReduce 有什么区别?

深度解析: 随着MongoDB 4.2版本的发布,MapReduce已逐渐被废弃,聚合框架成为首选。

特性 聚合框架 (Aggregation) MapReduce
性能 高性能,C++实现,管道优化 较慢,JavaScript引擎执行
易用性 声明式,链式调用,易于理解 命令式,需编写JS函数
功能 覆盖80%常见场景 理论上支持所有逻辑
状态 推荐,活跃维护 已废弃 (Deprecated)

Q3: MongoDB 支持事务吗?

深度解析: MongoDB 3.6 版本开始支持多文档事务,但仅适用于副本集(Replica Sets)和分片集群(Sharded Clusters)。

事务特性遵循 ACID 原则,但需注意:

  • 事务只能在会话(Session)中开启。
  • 事务中只能操作同一个数据库中的集合。
  • 长事务会影响性能,建议保持事务简短。
  • 需要设置 w: "majority" 以确保数据持久性。
// 开启事务示例 const session = client.startSession(); try { await session.withTransaction(async () => { await accounts.collection('accounts') .updateOne({ name: 'A' }, { $inc: { balance: -100 } }); await accounts.collection('accounts') .updateOne({ name: 'B' }, { $inc: { balance: 100 } }); }); } finally { await session.endSession(); }

Q4: 什么是分片(Sharding)?如何选择分片键?

深度解析: 分片是将数据分布到多个机器上的过程,用于支持大数据集的部署和高吞吐操作。

分片键选择原则:

  • 高基数(High Cardinality): 分片键的值应尽可能分散,避免数据倾斜。
  • 查询模式: 分片键应包含在大多数查询中,以减少跨节点查询(Scatter-Gather)。
  • 单调递增 vs 随机: 单调递增键(如时间戳)可能导致热点写入;随机键(如Hash)可均匀分布但可能增加查询开销。

Q5: 如何进行数据迁移?

深度解析: 数据迁移是运维中的常见任务,MongoDB提供了多种工具:

  • MongoDB Compass: 图形化工具,适合小数据量导入导出。
  • mongoimport/mongoexport: 命令行工具,支持CSV、JSON、BSON格式。
  • MongoDB Atlas Data Federation: 云原生方案,适合跨云迁移。
  • Change Streams: 用于实时数据同步,实现零停机迁移。

三、 MongoDB 进阶架构设计

阶段一:副本集(Replica Set)

副本集提供高可用性(HA)。至少包含一个主节点(Primary)和两个从节点(Secondary)。主节点处理写操作,从节点同步数据并处理读操作。故障自动切换(Failover)是核心特性。

阶段二:分片集群(Sharded Cluster)

当数据量超过单机存储或吞吐量瓶颈时,引入分片。集群由三部分组成:

  • Config Server: 存储集群元数据。
  • Mongos: 路由服务器,客户端连接入口。
  • Shard: 实际存储数据的副本集。
阶段三:事务与一致性

MongoDB 4.0+ 支持跨分片事务。使用两阶段提交(2PC)协议保证一致性。开发者需权衡一致性与性能,适当放宽一致性要求(如最终一致性)可提升系统吞吐量。

四、 MongoDB 性能优化实战

📈 查询优化

使用 explain() 分析查询计划。重点关注 IXSCAN(索引扫描)和 COLSCAN(集合扫描)。避免全表扫描,确保查询条件命中索引。

💾 存储优化

启用压缩(Compression)减少磁盘占用。使用预分配文件(Pre-allocating Files)避免频繁磁盘扩展。定期运行 reIndex 重建碎片化索引。

🚀 内存管理

MongoDB 使用 WiredTiger 存储引擎,支持页缓存。确保 cacheSizeGB 设置合理,通常建议为物理内存的 50%-70%。监控 page faults 指标,过高说明缓存不足。