MongoDB - 性能和集合大小
MongoDB - performance and collection size
我有一个关于集合大小和查询性能的问题 –
有 2 个数据库——DB1 和 DB2。 DB1 有 1 个集合,这是该集合上 stats() 的输出 –
{
…
"count" : 2085217,
"size" : 17048734192,
"avgObjSize" : 8176,
"capped" : false,
"nindexes" : 3,
"indexDetails" : {},
"totalIndexSize" : 606299456,
"indexSizes" : {
"_id_" : 67664576,
"id_1" : 284165056,
"id_2" : 254469824
},
…
}
使用索引 id_1 对此集合的查询在 0.012 秒后返回。这是 explain() -
的输出
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 0,
"totalKeysExamined" : 1,
"totalDocsExamined" : 1,
….
"indexName" : "id_1",
}
在 DB2 中,我有 4 个集合,这是 DB2 上统计信息的输出 –
{
…
"collections" : 4,
"objects" : 152655935,
"avgObjSize" : 8175.998307514215,
"dataSize" : 1248114666192,
"storageSize" : 1257144933456,
"indexes" : 12,
"indexSize" : 19757688272,
"fileSize" : 1283502112768,
…
}
使用我通过 explain() 确认的索引对 DB2 中的任何集合进行查询所花费的时间至少是之前针对 DB1 的查询所用时间的两倍。
既然mongo应该很好扩展,为什么会有这个差异?我读到 mongodb 加载内存中的所有索引,并且由于 DB2 的容量比 DB1 大,这就是它花费更长时间的原因吗?
任何见解都会非常有帮助。谢谢。
编辑 1:
添加更多信息。集合定义、索引定义和执行的查询...
所有集合(在两个数据库中)都包含相同的字段;它们之间只有值和文档大小不同。
而且,这是相关索引 -
"1" : {
"v" : 1,
"unique" : true,
"key" : {
"id" : 1
},
"name" : "id_1",
"ns" : "ns.coll1"
}
而且,id 字段是这样的:
"_id" : ObjectId("55f9b6548aefbce6b2fa2fac"),
"id" : {
"pid" : {
"f1" : "val1",
"f2" : "val2"
}
},
而且,这是一个示例查询 -
db.coll1.find({id:{pid:{f1:"val1",f2:"val2"}}})
编辑 2:
这是有关硬盘和 RAM 的更多信息 -
$ free -m
total used free shared buff/cache available
Mem: 386758 3750 1947 25283 381060 355675
Swap: 131071 3194 127877
硬盘3.5T左右,其中2.9T已用
缩放
Mongo数据库扩展性非常好。问题是,它被设计为水平缩放,而不是垂直缩放。这意味着如果您的数据库包含大量数据,您应该对集合进行分片以实现更好的并行化。
基准测试结果
关于查询时间的差异,我不认为你的分析是决定性的。数据库可能在不同的机器上(具有不同的规格)。假设硬件相同,DB2 显然在其集合中拥有更多文档,并且两个 DB 上文档的大小也不相同。同一个查询可以 return 个不同大小的数据集。这将不可避免地对数据序列化和其他低级别方面产生影响。除非您在更受控制的设置中分析查询,否则我认为您的结果非常符合预期。
建议
如果您在文档上使用 DRef,请小心。它可能 Mongo 会自动取消引用它们;这意味着更多的数据需要序列化和开销。
尝试 运行 使用 limit
规范进行相同的查询。您已将索引定义为唯一的,但我不知道这是否会在 Mongo 找到值后自动停止索引遍历。检查 db.coll1.find({id:{pid:{f1:"val1",f2:"val2"}}})
和 db.coll1.find({id:{pid:{f1:"val1",f2:"val2"}}}).limit(1)
运行 是否同时出现。
看看Indexes on embedded fields and Indexes on embedded documents。嵌入式文档似乎会影响额外的开销。
最后,如果你的文档没有嵌入文档,只有嵌入字段(似乎是这样),那么更具体地定义你的索引。创建这个索引
db.coll1.createIndex({"id.pid.f1": 1, "id.pid.f2": 1}, {unique: true})
和运行再次查询。如果该索引没有提高性能,那么我相信您已正确完成所有操作,可能是时候开始 sharding.
我有一个关于集合大小和查询性能的问题 –
有 2 个数据库——DB1 和 DB2。 DB1 有 1 个集合,这是该集合上 stats() 的输出 –
{
…
"count" : 2085217,
"size" : 17048734192,
"avgObjSize" : 8176,
"capped" : false,
"nindexes" : 3,
"indexDetails" : {},
"totalIndexSize" : 606299456,
"indexSizes" : {
"_id_" : 67664576,
"id_1" : 284165056,
"id_2" : 254469824
},
…
}
使用索引 id_1 对此集合的查询在 0.012 秒后返回。这是 explain() -
的输出"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 0,
"totalKeysExamined" : 1,
"totalDocsExamined" : 1,
….
"indexName" : "id_1",
}
在 DB2 中,我有 4 个集合,这是 DB2 上统计信息的输出 –
{
…
"collections" : 4,
"objects" : 152655935,
"avgObjSize" : 8175.998307514215,
"dataSize" : 1248114666192,
"storageSize" : 1257144933456,
"indexes" : 12,
"indexSize" : 19757688272,
"fileSize" : 1283502112768,
…
}
使用我通过 explain() 确认的索引对 DB2 中的任何集合进行查询所花费的时间至少是之前针对 DB1 的查询所用时间的两倍。
既然mongo应该很好扩展,为什么会有这个差异?我读到 mongodb 加载内存中的所有索引,并且由于 DB2 的容量比 DB1 大,这就是它花费更长时间的原因吗?
任何见解都会非常有帮助。谢谢。
编辑 1: 添加更多信息。集合定义、索引定义和执行的查询...
所有集合(在两个数据库中)都包含相同的字段;它们之间只有值和文档大小不同。
而且,这是相关索引 -
"1" : {
"v" : 1,
"unique" : true,
"key" : {
"id" : 1
},
"name" : "id_1",
"ns" : "ns.coll1"
}
而且,id 字段是这样的:
"_id" : ObjectId("55f9b6548aefbce6b2fa2fac"),
"id" : {
"pid" : {
"f1" : "val1",
"f2" : "val2"
}
},
而且,这是一个示例查询 -
db.coll1.find({id:{pid:{f1:"val1",f2:"val2"}}})
编辑 2: 这是有关硬盘和 RAM 的更多信息 -
$ free -m
total used free shared buff/cache available
Mem: 386758 3750 1947 25283 381060 355675
Swap: 131071 3194 127877
硬盘3.5T左右,其中2.9T已用
缩放
Mongo数据库扩展性非常好。问题是,它被设计为水平缩放,而不是垂直缩放。这意味着如果您的数据库包含大量数据,您应该对集合进行分片以实现更好的并行化。
基准测试结果
关于查询时间的差异,我不认为你的分析是决定性的。数据库可能在不同的机器上(具有不同的规格)。假设硬件相同,DB2 显然在其集合中拥有更多文档,并且两个 DB 上文档的大小也不相同。同一个查询可以 return 个不同大小的数据集。这将不可避免地对数据序列化和其他低级别方面产生影响。除非您在更受控制的设置中分析查询,否则我认为您的结果非常符合预期。
建议
如果您在文档上使用 DRef,请小心。它可能 Mongo 会自动取消引用它们;这意味着更多的数据需要序列化和开销。
尝试 运行 使用
limit
规范进行相同的查询。您已将索引定义为唯一的,但我不知道这是否会在 Mongo 找到值后自动停止索引遍历。检查db.coll1.find({id:{pid:{f1:"val1",f2:"val2"}}})
和db.coll1.find({id:{pid:{f1:"val1",f2:"val2"}}}).limit(1)
运行 是否同时出现。看看Indexes on embedded fields and Indexes on embedded documents。嵌入式文档似乎会影响额外的开销。
最后,如果你的文档没有嵌入文档,只有嵌入字段(似乎是这样),那么更具体地定义你的索引。创建这个索引
db.coll1.createIndex({"id.pid.f1": 1, "id.pid.f2": 1}, {unique: true})
和运行再次查询。如果该索引没有提高性能,那么我相信您已正确完成所有操作,可能是时候开始 sharding.