【发布时间】:2020-05-20 17:43:06
【问题描述】:
我有一个非常简单的集合,除了 _id 之外没有任何索引。
每个文档都包含一个数组字段mies。
当前的集合大小约为 1 亿,我可以在分析器中看到以下异常:
{
"op": "update",
"ns": "DB.links",
"command": {
"q": {
"_id": "f1b54f37-7f92-4e75-9ec6-5329349ce792_eb370c8a-6f33-4989-aa59-a26e1c9df46c"
},
"u": {
"$push": {
"mies": {
"$each": [
{
"$oid": "5e39d07bec34b8000e7f86b7"
}
]
}
}
},
"multi": true,
"upsert": true
},
"keysExamined": 0,
"docsExamined": 0,
"nMatched": 0,
"nModified": 0,
"upsert": true,
"keysInserted": 1,
"numYield": 0,
"locks": {
"Global": {
"acquireCount": {
"r": 2,
"w": 2
}
},
"Database": {
"acquireCount": {
"w": 2
},
"acquireWaitCount": {
"w": 1
},
"timeAcquiringMicros": {
"w": 19486143
}
},
"Collection": {
"acquireCount": {
"w": 1
}
},
"oplog": {
"acquireCount": {
"w": 1
}
}
},
"millis": 19490,
"planSummary": "IDHACK",
"execStats": {
"stage": "UPDATE",
"nReturned": 0,
"executionTimeMillisEstimate": 0,
"works": 2,
"advanced": 0,
"needTime": 1,
"needYield": 0,
"saveState": 0,
"restoreState": 0,
"isEOF": 1,
"invalidates": 0,
"nMatched": 0,
"nWouldModify": 0,
"nInvalidateSkips": 0,
"wouldInsert": true,
"fastmodinsert": false,
"inputStage": {
"stage": "IDHACK",
"nReturned": 0,
"executionTimeMillisEstimate": 0,
"works": 1,
"advanced": 0,
"needTime": 0,
"needYield": 0,
"saveState": 0,
"restoreState": 0,
"isEOF": 1,
"invalidates": 0,
"keysExamined": 0,
"docsExamined": 0
}
}
}
如您所见,一个带有单个 $push 到数组的简单 upsert 需要 19 秒。 我相信大部分时间都花在了这里:
"timeAcquiringMicros": {
"w": 19486143
}
我应该检查什么?如何提高性能?
【问题讨论】:
-
因为你只查询
_id这是一个默认的索引字段,所以查询是安静的,但关心的是1亿个文档,也许你为什么不考虑分片或如果大量读取不需要,以某种方式归档旧记录? -
可以,但是由于业务逻辑,数据要积累一段时间。我可以看到热集合的索引大小超过了 MongoDB 的缓存大小。这就是锁慢的原因吗?
-
我会说至少将该集合与其他集合分开并在可能的情况下将其单独维护在不同的集群中(如果您不想进行分片并希望所有文档都在同一个集群上) - 那样您可以拥有足够好的集群大小(RAM + 磁盘)来满足该集合以及高 I/O... 检查此文档 :: docs.mongodb.com/manual/tutorial/ensure-indexes-fit-ram
标签: mongodb query-optimization