如何提高 MongoDB 插入性能
How to improve MongoDB insert performance
结果:
如果您正在对一个容错的数据集进行操作,或者执行您可以验证的一次性过程,将 WriteAcknowledge 更改为 Unacknowledged 会有所帮助。
此外,默认情况下,批量操作是 IsOrdered,我没有意识到这一点。将此设置为 False 实际上会使操作批量执行,否则它将作为一个更新线程运行。
MongoDB 3.0/WiredTiger/C# 驱动程序
我有一个包含 147,000,000 个文档的集合,我每秒(希望如此)对其中的文档进行大约 1 次更新。 3000 个文档。
这是一个示例更新:
"query" : {
"_id" : BinData(0,"UKnZwG54kOpT4q9CVWbf4zvdU223lrE5w/uIzXZcObQiAAAA")
},
"updateobj" : {
"$set" : {
"b" : BinData(0,"D8u1Sk/fDES4IkipZzme7j2qJ4oWjlT3hvLiAilcIhU="),
"s" : true
}
}
这是一个典型的更新,我要求以每秒 3000 条的速度插入。
不幸的是,这些花费的时间是原来的两倍,例如上次更新是针对 1723 个文档,耗时 1061 毫秒。
集合只有 _id 上的索引,没有其他索引,集合的平均文档大小为 244 字节,无上限。
服务器内存64GB,12个线程。插入性能在较小的集合大小下非常出色,比如大约 5000 万,但在大约 8000 万之后真正开始下降。
会不会是整集不在内存中?数据库由 RAID0 SSD 支持,因此 IO 性能不应成为瓶颈,如果是,它应该在一开始就显示出来吗?
希望得到一些指导,因为我有信心 Mongo与使用它的某些应用程序相比,DB 可以满足我相当微不足道的要求。数据库的读取率不高,因此分片不会改进很重要,虽然也许我错了。
不管怎样,目前的插入率都不够好。
更新:这里是查询的 explain()...
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "Collection",
"indexFilterSet" : false,
"parsedQuery" : {
"_id" : {
"$eq" : { "$binary" : "SxHHwTMEaOmSc9dD4ng/7ILty0Zu0qX38V81osVqWkAAAAAA", "$type" : "00" }
}
},
"winningPlan" : {
"stage" : "IDHACK"
},
"rejectedPlans" : []
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 1,
"totalKeysExamined" : 1,
"totalDocsExamined" : 1,
"executionStages" : {
"stage" : "IDHACK",
"nReturned" : 1,
"executionTimeMillisEstimate" : 0,
"works" : 2,
"advanced" : 1,
"needTime" : 0,
"needFetch" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"keysExamined" : 1,
"docsExamined" : 1
},
"allPlansExecution" : []
},
它自己的查询非常快,更新操作大约需要 25 毫秒,它们正在使用 BulkWriter 推送到 Mongo:await m_Collection.BulkWriteAsync(updates);
我们切换到 Cassandra 是因为 Mongo 扩展性不佳。如果你说在 80M 之后你看到性能下降,很容易与内存有关。
我更擅长 SQL 数据库,但我不会说非关键字段更新的 25 毫秒令人印象深刻。我怀疑类似的更新会在 Oracle 上执行得更好,MySql,...
您可以尝试修改Write concern levels。
显然这存在风险,因为您将无法捕捉到任何写入错误,但至少您仍然应该能够捕捉到网络错误。
由于 MongoDB 将批量插入操作分组在 groups of 1000 中,因此 应该 加快该过程。
W 默认为 1:
当您将其更改为 0 时:
如果您不关心元素的顺序,调用无序批量操作可以获得一些速度
await m_Collection.BulkWriteAsync(updates, new BulkWriteOptions() { IsOrdered = false });
With an unordered operations list, MongoDB can execute in parallel the
write operations in the list and in any order. Link
"There is not a substantial read rate on the database so Sharding
would not improve matters, although perhaps I am wrong."
更新涉及读取。又名发现被遗弃的 _id——所以如果没有帮助的话,分片可能会有帮助
这里标记的答案很好。我想添加一个额外的代码来帮助其他使用 InsertMany
而不是 BulkWriteAsync
的人更快地利用 IsOrdered = false
m_Collection.InsertMany(listOfDocument, new InsertManyOptions() { IsOrdered = false });
结果:
如果您正在对一个容错的数据集进行操作,或者执行您可以验证的一次性过程,将 WriteAcknowledge 更改为 Unacknowledged 会有所帮助。
此外,默认情况下,批量操作是 IsOrdered,我没有意识到这一点。将此设置为 False 实际上会使操作批量执行,否则它将作为一个更新线程运行。
MongoDB 3.0/WiredTiger/C# 驱动程序
我有一个包含 147,000,000 个文档的集合,我每秒(希望如此)对其中的文档进行大约 1 次更新。 3000 个文档。
这是一个示例更新:
"query" : {
"_id" : BinData(0,"UKnZwG54kOpT4q9CVWbf4zvdU223lrE5w/uIzXZcObQiAAAA")
},
"updateobj" : {
"$set" : {
"b" : BinData(0,"D8u1Sk/fDES4IkipZzme7j2qJ4oWjlT3hvLiAilcIhU="),
"s" : true
}
}
这是一个典型的更新,我要求以每秒 3000 条的速度插入。
不幸的是,这些花费的时间是原来的两倍,例如上次更新是针对 1723 个文档,耗时 1061 毫秒。
集合只有 _id 上的索引,没有其他索引,集合的平均文档大小为 244 字节,无上限。
服务器内存64GB,12个线程。插入性能在较小的集合大小下非常出色,比如大约 5000 万,但在大约 8000 万之后真正开始下降。
会不会是整集不在内存中?数据库由 RAID0 SSD 支持,因此 IO 性能不应成为瓶颈,如果是,它应该在一开始就显示出来吗?
希望得到一些指导,因为我有信心 Mongo与使用它的某些应用程序相比,DB 可以满足我相当微不足道的要求。数据库的读取率不高,因此分片不会改进很重要,虽然也许我错了。
不管怎样,目前的插入率都不够好。
更新:这里是查询的 explain()...
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "Collection",
"indexFilterSet" : false,
"parsedQuery" : {
"_id" : {
"$eq" : { "$binary" : "SxHHwTMEaOmSc9dD4ng/7ILty0Zu0qX38V81osVqWkAAAAAA", "$type" : "00" }
}
},
"winningPlan" : {
"stage" : "IDHACK"
},
"rejectedPlans" : []
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 1,
"totalKeysExamined" : 1,
"totalDocsExamined" : 1,
"executionStages" : {
"stage" : "IDHACK",
"nReturned" : 1,
"executionTimeMillisEstimate" : 0,
"works" : 2,
"advanced" : 1,
"needTime" : 0,
"needFetch" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"keysExamined" : 1,
"docsExamined" : 1
},
"allPlansExecution" : []
},
它自己的查询非常快,更新操作大约需要 25 毫秒,它们正在使用 BulkWriter 推送到 Mongo:await m_Collection.BulkWriteAsync(updates);
我们切换到 Cassandra 是因为 Mongo 扩展性不佳。如果你说在 80M 之后你看到性能下降,很容易与内存有关。 我更擅长 SQL 数据库,但我不会说非关键字段更新的 25 毫秒令人印象深刻。我怀疑类似的更新会在 Oracle 上执行得更好,MySql,...
您可以尝试修改Write concern levels。 显然这存在风险,因为您将无法捕捉到任何写入错误,但至少您仍然应该能够捕捉到网络错误。 由于 MongoDB 将批量插入操作分组在 groups of 1000 中,因此 应该 加快该过程。
W 默认为 1:
当您将其更改为 0 时:
如果您不关心元素的顺序,调用无序批量操作可以获得一些速度
await m_Collection.BulkWriteAsync(updates, new BulkWriteOptions() { IsOrdered = false });
With an unordered operations list, MongoDB can execute in parallel the write operations in the list and in any order. Link
"There is not a substantial read rate on the database so Sharding would not improve matters, although perhaps I am wrong."
更新涉及读取。又名发现被遗弃的 _id——所以如果没有帮助的话,分片可能会有帮助
这里标记的答案很好。我想添加一个额外的代码来帮助其他使用 InsertMany
而不是 BulkWriteAsync
的人更快地利用 IsOrdered = false
m_Collection.InsertMany(listOfDocument, new InsertManyOptions() { IsOrdered = false });