前言
作为资料库管理的新手小白,在 MongoDB 应用方面实在没什么经验,採用 MongoDB 也只是为了方便储存不对称数据的优势,然而使用到现几个月了逐渐发现效能堪忧,于是开始了我的性能调校之路!
情境描述
在处理 AWS 帐单数据的 MongoDB 系统中,我们遇到了查询效能缓慢的问题,系统需要频繁地根据帐单期间(BillingPeriodStartDate)和帐户 ID(UsageAccountId)来查询数据,单一 collection 数据量已达到约 300 万笔记录。
问题诊断
1. 初始查询分析
首先,我的需求是使用以下查询来检索特定帐期和帐户的数据:
db.rawdata.find({
"lineItem/UsageAccountId": {
$in: [
"123456789001", "123456789002", "123456789003",
// ... 更多帐户 ID
]
},
"bill/BillingPeriodStartDate": "2024-11-01T00:00:00Z"
})
2. 使用 explain() 诊断查询效能
通过添加 explain("executionStats") 来分析查询执行情况:
db.rawdata.find({...}).explain("executionStats")
优化前的执行统计:
{
"executionStats": {
"executionSuccess": true,
"nReturned": 133696,
"executionTimeMillis": 8547,
"totalKeysExamined": 0,
"totalDocsExamined": 3109528,
"executionStages": {
"stage": "COLLSCAN",
// ... 省略其他细节
}
}
}
关键问题指标:
解决方案
1. 创建复合索引
根据查询需求,我创建了一个复合索引:
db.rawdata.createIndex({
"bill/BillingPeriodStartDate": 1,
"lineItem/UsageAccountId": 1
})
2. 验证索引创建
确认索引是否成功创建:
db.rawdata.getIndexes()
3. 重新执行查询分析
使用相同的 explain 命令检查优化效果:
db.rawdata.find({...}).explain("executionStats")
优化后的执行统计:
{
"executionStats": {
"executionSuccess": true,
"nReturned": 133696,
"executionTimeMillis": 1247,
"totalKeysExamined": 133730,
"totalDocsExamined": 133696,
"executionStages": {
"stage": "FETCH",
"inputStage": {
"stage": "IXSCAN",
// ... 省略其他细节
}
}
}
}
效能改善分析
通过对比优化前后的关键指标:
查询耗时:
- 优化前:8547 毫秒
- 优化后:1247 毫秒
- 改善幅度:约 85%
扫描文档数:
- 优化前:3,109,528 文档
- 优化后:133,730 文档
- 减少幅度:约 95%
查询方式:
- 优化前:COLLSCAN(全集合扫描)
- 优化后:IXSCAN(索引扫描)
小结
本文透过 explain() 分析查询效能低落的癥结点,并建立有效索引,达到巨幅提升查询的效能,但这仅仅只是调优的一小部分,我目前还遇到其他问题尚未解决,在问题解决以后,会再跟大家分享,请各位敬请期待!