Appearance
性能优化
MongoDB性能优化是数据库管理中的重要环节。本章将介绍查询优化、索引优化、服务器配置优化等方面的知识。
性能优化概述
优化目标
javascript
// MongoDB性能优化的主要目标:
// 1. 缩短查询响应时间
// 2. 提高系统吞吐量
// 3. 降低资源消耗
// 4. 提升用户体验
// 优化原则:
// 1. 先诊断问题,再进行优化
// 2. 优化要有针对性,避免过度优化
// 3. 优化后要验证效果
// 4. 记录优化过程和结果优化层次
javascript
// MongoDB性能优化可以分为多个层次:
// 1. 查询层优化
// 优化查询语句、使用索引
// 2. 数据模型优化
// 文档结构设计、嵌套vs引用
// 3. 索引优化
// 索引设计、索引维护
// 4. 服务器配置优化
// 内存、连接数、缓存配置
// 5. 架构优化
// 复制集、分片集群查询优化
使用explain分析查询
javascript
// explain是分析查询执行计划的重要工具
// 基本用法
db.users.find({ name: "张三" }).explain()
// 详细模式
db.users.find({ name: "张三" }).explain("executionStats")
// 全部信息
db.users.find({ name: "张三" }).explain("allPlansExecution")
// 输出关键字段说明:
// - winningPlan: 被选中的执行计划
// - stage: 执行阶段
// - COLLSCAN: 全表扫描
// - IXSCAN: 索引扫描
// - FETCH: 获取文档
// - indexName: 使用的索引名称
// - executionTimeMillis: 执行时间(毫秒)
// - totalDocsExamined: 扫描的文档数
// - nReturned: 返回的文档数
// 判断是否使用索引
var plan = db.users.find({ name: "张三" }).explain()
if (plan.queryPlanner.winningPlan.stage === "COLLSCAN") {
print("全表扫描,未使用索引")
} else if (plan.queryPlanner.winningPlan.stage === "IXSCAN") {
print("使用了索引")
}查询优化技巧
javascript
// 查询优化技巧
// 1. 避免全表扫描
// 使用索引覆盖查询条件
// 2. 使用投影减少返回数据
db.users.find({ status: "active" }, { name: 1, email: 1, _id: 0 })
// 3. 使用limit限制结果集
db.users.find({ status: "active" }).limit(100)
// 4. 避免使用$where
// $where会执行JavaScript,性能较差
// 5. 避免使用$regex前缀通配符
// 不推荐
db.users.find({ name: /张/ }) // 无法使用索引
// 推荐
db.users.find({ name: /^张/ }) // 可以使用索引
// 6. 使用hint强制使用索引
db.users.find({ name: "张三" }).hint({ name: 1 })
// 7. 批量操作代替循环操作
// 不推荐
for (var i = 0; i < 1000; i++) {
db.users.insertOne({ name: "user" + i })
}
// 推荐
var docs = []
for (var i = 0; i < 1000; i++) {
docs.push({ name: "user" + i })
}
db.users.insertMany(docs)覆盖索引
javascript
// 覆盖索引:查询的所有字段都在索引中,不需要回表
// 创建复合索引
db.users.createIndex({ name: 1, email: 1 })
// 使用覆盖索引查询
db.users.find(
{ name: "张三" },
{ _id: 0, name: 1, email: 1 } // 只返回索引字段
)
// 验证是否使用覆盖索引
var plan = db.users.find(
{ name: "张三" },
{ _id: 0, name: 1, email: 1 }
).explain("executionStats")
// 如果totalDocsExamined为0,说明使用了覆盖索引
print("扫描文档数: " + plan.executionStats.totalDocsExamined)索引优化
索引设计原则
javascript
// 索引设计原则
// 1. ESR原则(Equality-Sort-Range)
// 等值查询字段 -> 排序字段 -> 范围查询字段
// 示例查询
db.orders.find({ status: "completed" })
.sort({ createdAt: -1 })
.limit(100)
// 推荐索引
db.orders.createIndex({ status: 1, createdAt: -1 })
// 2. 选择性高的字段优先
// 选择性 = 不同值数量 / 总文档数
// 选择性越高,索引效果越好
// 3. 避免过多索引
// 索引占用存储空间,影响写入性能
// 建议单集合索引不超过5-10个
// 4. 使用复合索引代替多个单字段索引
// 5. 定期检查索引使用情况
db.users.aggregate([
{ $indexStats: {} }
])索引维护
javascript
// 索引维护操作
// 查看索引使用情况
db.users.aggregate([
{ $indexStats: {} },
{ $match: { accesses: { $eq: 0 } } } // 查找未使用的索引
])
// 删除未使用的索引
db.users.dropIndex("unused_index")
// 重建索引(减少碎片)
db.users.reIndex()
// 查看索引大小
db.users.totalIndexSize()
// 后台创建索引(不阻塞操作)
db.users.createIndex({ name: 1 }, { background: true })服务器配置优化
内存配置
yaml
# mongod.conf 内存相关配置
storage:
# WiredTiger缓存大小(建议物理内存的50%-60%)
wiredTiger:
engineConfig:
cacheSizeGB: 4
# 日志配置
journal:
enabled: true
# 网络配置
net:
# 最大连接数
maxIncomingConnections: 65536连接池配置
javascript
// 应用程序连接池配置(以Node.js为例)
const { MongoClient } = require('mongodb')
const client = new MongoClient('mongodb://localhost:27017', {
// 连接池大小
maxPoolSize: 100,
// 最小连接数
minPoolSize: 10,
// 连接超时时间
connectTimeoutMS: 30000,
// Socket超时时间
socketTimeoutMS: 360000,
// 最大闲置时间
maxIdleTimeMS: 60000,
// 等待队列超时
waitQueueTimeoutMS: 5000
})监控与诊断
服务器状态
javascript
// 查看服务器状态
db.serverStatus()
// 关键指标:
// - connections: 连接信息
// - opcounters: 操作计数
// - memory: 内存使用
// - network: 网络统计
// - wiredTiger: 存储引擎统计
// 查看当前操作
db.currentOp()
// 查看慢操作
db.currentOp({
"secs_running": { $gt: 5 } // 运行超过5秒的操作
})
// 终止长时间运行的操作
db.killOp(opId)数据库统计
javascript
// 查看数据库统计
db.stats()
// 查看集合统计
db.users.stats()
// 查看集合存储大小
db.users.storageSize()
// 查看集合索引大小
db.users.totalIndexSize()性能分析
javascript
// 开启性能分析
db.setProfilingLevel(1, 50) // 记录超过50ms的操作
// 查看分析级别
db.getProfilingLevel()
// 查看慢查询
db.system.profile.find().sort({ ts: -1 }).limit(10)
// 关闭性能分析
db.setProfilingLevel(0)本章小结
本章介绍了MongoDB性能优化的相关知识:
- 优化概述:理解优化的目标和层次
- 查询优化:学会使用explain分析查询,掌握优化技巧
- 索引优化:掌握索引设计原则和维护方法
- 服务器配置:了解内存和连接池配置
- 监控诊断:学会使用各种监控工具诊断问题
下一章,我们将学习复制集,了解MongoDB的高可用架构。
