MongoDB性能优化 #

一、性能优化概述 #

1.1 优化方向 #

方向 说明
查询优化 优化查询语句和索引
索引优化 设计合适的索引策略
配置优化 调整MongoDB配置
架构优化 优化数据库架构
硬件优化 升级硬件资源

1.2 性能指标 #

指标 说明
QPS 每秒查询数
延迟 查询响应时间
吞吐量 数据处理量
资源使用 CPU、内存、磁盘

二、查询优化 #

2.1 使用explain分析 #

javascript
// 基本分析
db.users.find({ name: "John" }).explain()

// 详细分析
db.users.find({ name: "John" }).explain("executionStats")

// 关键指标
{
    executionStats: {
        totalDocsExamined: 1000,    // 扫描文档数
        totalKeysExamined: 1000,    // 扫描索引键数
        nReturned: 10,              // 返回文档数
        executionTimeMillis: 5      // 执行时间
    }
}

2.2 优化查询语句 #

javascript
// 不推荐:全表扫描
db.users.find({ name: /John/ })

// 推荐:使用索引
db.users.find({ name: /^John/ })

// 不推荐:使用$where
db.users.find({ $where: "this.age > 20" })

// 推荐:使用操作符
db.users.find({ age: { $gt: 20 } })

// 不推荐:返回所有字段
db.users.find({ name: "John" })

// 推荐:只返回需要的字段
db.users.find({ name: "John" }, { name: 1, email: 1 })

2.3 使用投影 #

javascript
// 减少返回字段
db.users.find(
    { status: "active" },
    { name: 1, email: 1, _id: 0 }
)

2.4 使用limit #

javascript
// 限制返回数量
db.users.find().limit(100)

// 分页查询
db.users.find().skip(100).limit(100)

2.5 避免慢查询 #

javascript
// 开启慢查询日志
db.setProfilingLevel(1, 100)  // 记录超过100ms的查询

// 查看慢查询
db.system.profile.find().sort({ ts: -1 }).limit(10)

// 分析慢查询
db.system.profile.aggregate([
    { $group: { _id: "$ns", count: { $sum: 1 }, avgTime: { $avg: "$millis" } } },
    { $sort: { avgTime: -1 } }
])

三、索引优化 #

3.1 创建合适的索引 #

javascript
// 单字段索引
db.users.createIndex({ email: 1 })

// 复合索引
db.users.createIndex({ status: 1, createdAt: -1 })

// 多键索引
db.users.createIndex({ tags: 1 })

// 文本索引
db.articles.createIndex({ content: "text" })

3.2 索引设计原则 #

text
索引设计原则

1. 选择性高的字段
   - 区分度高的字段
   - 避免在低基数字段创建索引

2. 查询模式匹配
   - 根据查询模式设计索引
   - 复合索引遵循最左前缀

3. 排序优化
   - 排序字段考虑索引
   - 复合索引支持排序

4. 覆盖查询
   - 查询字段都在索引中
   - 避免回表查询

3.3 覆盖查询 #

javascript
// 创建复合索引
db.users.createIndex({ name: 1, email: 1 })

// 覆盖查询(只查询索引字段)
db.users.find(
    { name: "John" },
    { name: 1, email: 1, _id: 0 }
)

// 验证是否覆盖查询
db.users.find({ name: "John" }, { name: 1, email: 1, _id: 0 }).explain()
// 查看executionStats.totalDocsExamined是否为0

3.4 索引监控 #

javascript
// 查看索引使用情况
db.users.aggregate([
    { $indexStats: {} }
])

// 查找未使用的索引
db.users.aggregate([
    { $indexStats: {} },
    { $match: { "accesses.ops": 0 } }
])

// 查看索引大小
db.users.stats().indexSizes

3.5 删除冗余索引 #

javascript
// 查看冗余索引
// 如果有索引 { a: 1, b: 1 },则索引 { a: 1 } 是冗余的

// 删除冗余索引
db.users.dropIndex("a_1")

四、配置优化 #

4.1 内存配置 #

yaml
# mongod.conf
storage:
  wiredTiger:
    engineConfig:
      cacheSizeGB: 4  # 缓存大小(建议50%系统内存)

4.2 连接配置 #

yaml
# mongod.conf
net:
  maxIncomingConnections: 65536

4.3 日志配置 #

yaml
# mongod.conf
systemLog:
  verbosity: 0
  quiet: false
  logRotate: rename

4.4 写关注配置 #

javascript
// 设置默认写关注
db.adminCommand({
    setDefaultRWConcern: 1,
    defaultWriteConcern: { w: "majority" }
})

五、架构优化 #

5.1 分片优化 #

javascript
// 选择合适的分片键
sh.shardCollection("mydb.users", { userId: "hashed" })

// 预分割Chunk
sh.splitAt("mydb.users", { userId: 1000 })
sh.splitAt("mydb.users", { userId: 2000 })

5.2 复制集优化 #

javascript
// 读写分离
db.getMongo().setReadPref("secondaryPreferred")

// 使用标签
db.users.find().readPref("secondary", [{ dc: "east" }])

5.3 集合设计优化 #

javascript
// 嵌套文档 vs 引用文档
// 嵌套文档:适合一对一、一对少
{
    user: {
        name: "John",
        address: { city: "Beijing" }
    }
}

// 引用文档:适合一对多、多对多
{
    user: { _id: 1, name: "John" },
    orders: [{ orderId: 1 }, { orderId: 2 }]
}

六、硬件优化 #

6.1 存储优化 #

text
存储建议

1. 使用SSD
   - 随机IO性能更好
   - 降低延迟

2. RAID配置
   - RAID 10:性能和冗余
   - 避免RAID 5/6

3. 文件系统
   - XFS:推荐
   - ext4:兼容性好

6.2 内存优化 #

text
内存建议

1. 足够的内存
   - 工作集应该能放入内存
   - WiredTiger缓存50%系统内存

2. 避免交换
   - 关闭swap或限制使用

6.3 CPU优化 #

text
CPU建议

1. 多核CPU
   - MongoDB多线程
   - 更多核心更好

2. 高主频
   - 单线程操作更快

七、监控与诊断 #

7.1 服务器状态 #

javascript
// 查看服务器状态
db.serverStatus()

// 关键指标
{
    connections: { current: 100, available: 50000 },
    network: { bytesIn: 1000000, bytesOut: 2000000 },
    opcounters: { query: 1000, insert: 500, update: 200 },
    memory: { resident: 1024, virtual: 2048 }
}

7.2 数据库统计 #

javascript
// 查看数据库统计
db.stats()

// 查看集合统计
db.users.stats()

7.3 当前操作 #

javascript
// 查看当前操作
db.currentOp()

// 查看长时间运行的操作
db.currentOp({ "secs_running": { $gt: 5 } })

// 终止操作
db.killOp(opId)

7.4 性能监控工具 #

text
监控工具

1. MongoDB Atlas
   - 云监控
   - 性能洞察

2. MongoDB Compass
   - 可视化监控
   - 查询分析

3. Prometheus + Grafana
   - 自定义监控
   - 告警配置

4. MongoDB Ops Manager
   - 企业级监控
   - 自动化管理

八、常见性能问题 #

8.1 查询慢 #

javascript
// 分析原因
db.users.find({ name: "John" }).explain("executionStats")

// 解决方案
// 1. 创建索引
db.users.createIndex({ name: 1 })

// 2. 使用覆盖查询
db.users.find({ name: "John" }, { name: 1, email: 1, _id: 0 })

// 3. 限制返回数量
db.users.find({ name: "John" }).limit(100)

8.2 写入慢 #

javascript
// 分析原因
db.currentOp({ "op": "write" })

// 解决方案
// 1. 批量写入
db.users.insertMany([...])

// 2. 降低写关注
db.users.insertOne({...}, { writeConcern: { w: 1 } })

// 3. 无序写入
db.users.insertMany([...], { ordered: false })

8.3 内存不足 #

javascript
// 分析原因
db.serverStatus().memory

// 解决方案
// 1. 增加内存
// 2. 优化查询减少内存使用
// 3. 调整缓存大小

九、最佳实践 #

9.1 查询优化建议 #

text
1. 使用索引
2. 使用投影
3. 使用limit
4. 避免全表扫描
5. 使用覆盖查询

9.2 索引优化建议 #

text
1. 选择性高的字段
2. 复合索引设计
3. 删除冗余索引
4. 定期重建索引
5. 监控索引使用

9.3 配置优化建议 #

text
1. 合理配置内存
2. 调整连接数
3. 优化日志级别
4. 使用合适的写关注

十、总结 #

性能优化速查表:

优化方向 方法
查询优化 使用索引、投影、limit
索引优化 创建合适索引、删除冗余索引
配置优化 内存、连接、日志配置
架构优化 分片、复制集、集合设计
硬件优化 SSD、内存、CPU

常用诊断命令:

命令 说明
db.serverStatus() 服务器状态
db.stats() 数据库统计
db.currentOp() 当前操作
explain() 查询分析

恭喜你完成了MongoDB学习之旅!

最后更新:2026-03-27