分析MongoDB查询性能是确保应用程序高效运行的关键步骤。MongoDB提供了许多工具和命令,用于详细分析查询的性能表现。以下是详细的步骤和代码示例,展示如何分析MongoDB的查询性能。
1. 使用 explain 命令
explain 命令可以详细描述查询的执行计划,包括使用的索引、扫描的文档数量等。
示例:基本 explain 使用
javascript
db.students.find({ studentId: 12345 }).explain("executionStats");
输出示例及解读
json
{
"queryPlanner": {
"plannerVersion": 1,
"namespace": "school.students",
"indexFilterSet": false,
"parsedQuery": { "studentId": { "$eq": 12345 } },
"winningPlan": {
"stage": "FETCH",
"inputStage": {
"stage": "IXSCAN",
"keyPattern": { "studentId": 1 },
"indexName": "studentId_1",
"direction": "forward",
"indexBounds": { "studentId": [ "[12345, 12345]" ] }
}
},
"rejectedPlans": []
},
"executionStats": {
"executionSuccess": true,
"nReturned": 1,
"executionTimeMillis": 2,
"totalKeysExamined": 1,
"totalDocsExamined": 1,
"executionStages": {
"stage": "FETCH",
"nReturned": 1,
"executionTimeMillisEstimate": 0,
"works": 2,
"advanced": 1,
"needTime": 0,
"needYield": 0,
"saveState": 0,
"restoreState": 0,
"isEOF": 1,
"invalidates": 0,
"docsExamined": 1,
"alreadyHasObj": 0,
"inputStage": {
"stage": "IXSCAN",
"nReturned": 1,
"executionTimeMillisEstimate": 0,
"works": 2,
"advanced": 1,
"needTime": 0,
"needYield": 0,
"saveState": 0,
"restoreState": 0,
"isEOF": 1,
"invalidates": 0,
"keyPattern": { "studentId": 1 },
"indexName": "studentId_1",
"isMultiKey": false,
"multiKeyPaths": { "studentId": [] },
"indexBounds": { "studentId": [ "[12345, 12345]" ] },
"keysExamined": 1,
"seeks": 1,
"dupsTested": 0,
"dupsDropped": 0
}
}
},
"serverInfo": {
"host": "localhost",
"port": 27017,
"version": "4.4.6",
"gitVersion": "22c124145fa3bfdaeafb3f6d1b5f3d4e8391fe86"
}
}
关键指标说明:
totalKeysExamined: 扫描的索引键数量。totalDocsExamined: 扫描的文档数量。数字越小越好。executionTimeMillis: 查询执行时间,单位是毫秒。winningPlan: 使用的执行计划,包括使用的索引。
2. 使用 MongoDB Profiler
MongoDB Profiler 可以记录数据库操作和慢查询的详细信息。
启用 Profiler
javascript
db.setProfilingLevel(2);
查询 Profiler 数据
javascript
db.system.profile.find().sort({ ts: -1 }).limit(1).pretty();
关闭 Profiler
javascript
db.setProfilingLevel(0);
示例输出
json
{
"op": "query",
"ns": "school.students",
"command": {
"find": "students",
"filter": { "studentId": 12345 },
"projection": {},
"sort": {}
},
"keysExamined": 1,
"docsExamined": 1,
"cursorExhausted": true,
"numYield": 0,
"locks": {
"Global": { "acquireCount": { "r": 1 } },
"Database": { "acquireCount": { "r": 1 } },
"Collection": { "acquireCount": { "r": 1 } }
},
"nreturned": 1,
"responseLength": 466,
"millis": 2,
"ts": ISODate("2021-07-20T14:45:14.467Z"),
"client": "127.0.0.1",
"appName": "MongoDB Shell",
"allUsers": [],
"user": ""
}
关键指标说明:
keysExamined,docsExamined: 这些指标与explain命令的输出类似。millis: 查询执行时间,单位是毫秒。nreturned: 返回的文档数量。
3. 使用 db.currentOp() 命令
db.currentOp() 可以查看当前正在运行的操作。
示例:查看当前操作
javascript
db.currentOp();
示例输出
json
{
"inprog": [
{
"opid": 12345,
"active": true,
"secs_running": 2,
"microsecs_running": NumberLong(2000000),
"op": "query",
"ns": "school.students",
"query": { "studentId": 12345 },
"client": "127.0.0.1:50731",
"desc": "conn123",
"threadId": "0x7fd4e7bfb700",
"connectionId": 123,
"waitingForLock": false,
"lockStats": { "Global": { "acquireCount": { "r": NumberLong(1) } } }
}
]
}
关键指标说明:
secs_running: 查询已运行的时间,单位是秒。op: 当前正在执行的操作类型。query: 正在执行的查询。
4. 使用 Index Usage Statistics
查看索引的使用情况,识别未使用的索引。
示例:查看索引使用情况
javascript
db.students.aggregate([
{ $indexStats: {} }
]);
示例输出
json
[
{
"name": "studentId_1",
"key": { "studentId": 1 },
"host": "localhost:27017",
"accesses": {
"ops": 123,
"since": ISODate("2021-07-01T00:00:00Z")
}
}
]
关键指标说明:
name: 索引名称。accesses.ops: 索引的访问次数。accesses.since: 统计开始时间。
总结
通过上述方法,您可以详细分析MongoDB查询性能,并识别潜在的瓶颈和优化机会。关键工具和命令包括:
explain命令,详细描述查询执行计划。- MongoDB Profiler,记录数据库操作和慢查询。
db.currentOp()命令,查看当前正在运行的操作。- 索引使用统计,识别未使用的索引。
通过合理使用这些工具和方法,可以有效提高MongoDB查询的性能,从而确保数据库应用程序的高效运行。