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.