MongoDB 与关系型数据库的区别

  1. 数据模型

    • MongoDB 使用文档存储,每个文档采用 BSON 格式,能够嵌套结构化数组和对象,无需预先定义固定模式
    • 关系型数据库采用表格结构,数据以行和列形式存储,通常需要预定义格式
  2. 查询语言

    • MongoDB 使用基于 JSON 的查询语言,采用聚合管道实现复杂数据转化,查询灵活性高
    • 关系型数据库使用结构化查询语言 SQL, 但复杂查询可能影响性能
  3. 扩展性

    • MongoDB 天生支持水平扩展,可以跨多态服务器分布存储数据,适合大规模数据和高并发场景。
    • 关系型数据库通常依赖垂直扩展,不如 MongoDB 灵活
  4. 一致性与事务

    • MongoDB 在单文档操作上提供原子性,多文档事务从 V4.0 开始支持,但与关系型数据库相比仍有限。
    • 关系型数据库全面支持 ACID 事务,适合对数据一致性要求极高的场景。

MongoDB 的事务

  1. 性能: 强一致性事务会影响数据库的性能,而 mongoDB 的设计目标是高性能。
  2. 数据模型: 文档型数据库的数据模型相对灵活,但同时也增加了实现事务的复杂性。
  3. 使用场景: MongoDB 更适合用于存储非结构化数据和高并发读写场景,这些场景对事务的要求相对较低。
  4. 一致性: mongoDB 为了性能采用的是最终一致性,需要一段时间才能被所有节点看到,关系型数据库是强一致性。

在设计数据模型时,仍建议尽量利用单文档操作的原子性,只有在必要时才引入跨多文档的事务。

MongoDB 的索引类型有哪些?各自的优缺点是什么?

  1. 单字段索引(single Field)

    • 优点: 简单高效,适用精确匹配/排序
    • 缺点: 只优化单字段查询
  2. 复合索引(Compound Index)

    • 优点: 支持多字段联合查询/排序
    • 缺点: 仅最左前缀生效,占用更多内存
  3. 多键索引(MultiKey)

    • 优点: 自动为数组字段每个元素创建索引
    • 缺点: 大规模数组影响写入性能
  4. 文本索引(Text)

    • 优点: 支持全文搜索(含语言分词)
    • 缺点: 仅一个文本索引/权重管理复杂
  5. 地理空间索引(Geospatial)

    • 优点: 高效处理位置查询
    • 缺点: 仅适用地理坐标数据
  6. 哈希索引(Hashed)

    • 优点: 均匀分片支持, 快速等值查询
    • 缺点: 无法范围查询
  7. 通配符索引(Wildcard)

    • 优点: 动态字段查询优化
    • 缺点: 索引尺寸较大

MongoDB 的查询分析计划

db.collection.find().explain("executionStats") // 执行统计

executionStats 实际执行性能指标

1
2
3
4
5
6
"executionStats": {
"nReturned" : 5, // 返回文档数
"executionTimeMillis" : 2, // 执行时间(ms)
"totalKeysExamined" : 5, // 索引扫描次数
"totalDocsExamined" : 5 // 文档扫描次数
}

理想情况下 nReturned ≈ totalKeysExamined ≈ totalDocsExamined

COLLSCAN(全表扫描) vs IXSCAN(索引扫描)
▶︎ 应尽量避免出现 COLLSCAN

如何保证 MongoDB 的数据一致性?

  1. 写入层保障
1
2
3
4
5
6
7
8
// 强一致性写入配置
db.orders.insertOne({...}, {
writeConcern: {
w: "majority", // 确保数据写入大多数节点
j: true, // 写入journal日志保证持久性
wtimeout: 5000 // 超时设置(毫秒)
}
})
  1. 读取层控制
1
2
// 读取已提交的数据
db.products.find().readConcern("majority");

MongoDB 核心概念

  1. 为什么选择 MongoDB 而不是关系型数据库?

    • MongoDB 的文档模型更灵活,适合快速迭代的开发模式。
    • 它能处理大规模数据和高并发查询,支持水平扩展。
    • 适用于非结构化或半结构化数据,提供更高的开发效率。
  2. MongoDB 的文档模型与传统的关系模型有什么区别?

    • 在 MongoDB 中,数据存储为BSON 格式的文档,类似于 JSON,而关系型数据库使用表格和行。
    • 文档可以嵌套,支持复杂的数据结构,而关系型数据库需要多表关联。
  3. 什么是 BSON?它与 JSON 的区别是什么?

    • BSON(Binary JSON)是 JSON 的二进制表示形式,支持更多的数据类型(如日期、二进制数据)。
    • BSON 比 JSON 更高效,适合存储和传输。

数据操作与查询

  1. 如何执行 CRUD 操作?

    • CreateinsertOne()insertMany()
    • Readfind() 用于查询。
    • UpdateupdateOne()updateMany()
    • DeletedeleteOne()deleteMany()
  2. 什么是聚合管道?如何使用它?

    • 聚合管道是一系列的处理阶段(如$match$group$sort),用于对数据进行复杂处理。
    • 示例:
1
2
3
4
db.collection.aggregate([
{ $match: { status: "A" } },
{ $group: { _id: "$cust_id", total: { $sum: "$amount" } } },
]);
  1. 如何优化 MongoDB 查询性能?
    • 创建合适的索引,使用explain()分析查询计划。
    • 避免全集合扫描,减少返回的数据量。

索引与性能优化

  1. 什么是索引?如何在 MongoDB 中创建索引?
    • 索引是数据结构,用于加速查询。
    • 使用 createIndex() 创建索引,例如:
1
db.collection.createIndex({ field: 1 });
  1. 什么是复合索引?它的使用场景是什么?

    • 复合索引是包含多个字段的索引。
    • 适用于多字段组合查询的场景,例如 { field1: 1, field2: -1 }
  2. 如何监控和优化 MongoDB 的性能?

    • 使用 mongostatmongotopexplain("executionStats") 分析性能瓶颈。
    • 优化索引、分片和查询设计。

高可用性与集群管理

  1. 什么是复制集?它的作用是什么?

    • 复制集是一组维护相同数据集的 MongoDB 实例,提供高可用性数据冗余
    • 包括一个主节点和多个从节点。
  2. 什么是分片?它如何实现水平扩展?

    • 分片是将数据分布到多个服务器上的技术,用于处理大规模数据集。
    • 通过配置分片键实现数据分布。
  3. 如何管理 MongoDB 集群?

    • 使用 mongos 路由器管理分片集群,使用 mongod 管理复制集。
    • 监控集群状态,优化分片策略。

事务与一致性

  1. MongoDB 支持事务吗?如何使用?
    _ MongoDB 支持多文档事务,适用于需要原子性操作的场景。
    _ 示例:
1
2
3
session.startTransaction();
db.collection.insertOne({ field: "value" });
session.commitTransaction();
  1. 如何保证 MongoDB 中的数据一致性?
    • 对于复制集,使用"majority"读关注和写关注来确保强一致性。
    • 使用事务来保证多文档操作的一致性。

实践与工具

  1. 如何备份和恢复 MongoDB 数据?

    • 使用 mongodump 进行备份,mongorestore 进行恢复。
    • 也可以使用快照或云服务备份。
  2. 如何监控 MongoDB 的性能?

    • 使用 mongostatmongotop 实时监控数据库状态。
    • 集成 Prometheus 和 Grafana 进行长期性能分析。