mongodb更新导致读取速度极慢

时间:2013-03-01 14:42:45

标签: performance mongodb memory

我对mongoDB比较陌生。 我使用 2副本集设置了一个shard mongo集群;每个都设置在一个碎片中。 - > 4名mongo deamons

deamons分布在 2 WIN服务器上,每个服务器8gb ram 。 我有一个包含10个mio文档的测试集合(~600bytes / doc)并使用c#驱动程序连接到mongos(primaryPreferred)

现在,如果我在分片键上运行数千个单读取查询,我可以看到mongo占用的内存越来越多,并且停留在大约7,2GB左右。几乎没有页面错误,查询速度极快。好! 对不同文档属性的更复杂查询也是如此 (存在这些查询的综合索引)

但是

如果我只执行几个更新查询,我的内存使用率大幅下降......就像mongo 立刻释放3GB内存一样快速读取查询很慢。

如果我连续启动500k upserts(Save)会变得更糟。 运行时间为2秒的复杂查询现在需要22分钟。

对于具有相同查询参数的Count-Queries,我得到了相同的行为。

这是一个相当正常的mongoDB行为还是我错过了设置的东西?

---更新@hwatkins

  1. MongoDB版本:2.2.2
  2. 扫描了1个文件的单个文件
  3. 我在bulk-upsert期间有很高的磁盘活动
  4. 在upsert

    之前,

    explain()查询复杂的 count - 查询

    Count Explain: { "clusteredType" : "ParallelSort", "shards" : { "set1/xxxx:1234,yyyy:1234" : [{ "cursor" : "BtreeCursor AC", "isMultiKey" : false, "n" : 20799, "nscannedObjects" : 292741, "nscanned" : 292741, "nscannedObjectsAllPlans" : 294290, "nscannedAllPlans" : 294290, "scanAndOrder" : false, "indexOnly" : false, "nYields" : 2, "nChunkSkips" : 0, "millis" : 2382, "indexBounds" : { "f.14.b" : [["A", "A"]], "f.500.b" : [[10, 50]] }, "allPlans" : [{ "cursor" : "BtreeCursor AC", "n" : 20795, "nscannedObjects" : 292741, "nscanned" : 292741, "indexBounds" : { "f.14.b" : [["A", "A"]], "f.500.b" : [[10, 50]] } }, { "cursor" : "BasicCursor", "n" : 4, "nscannedObjects" : 1549, "nscanned" : 1549, "indexBounds" : { } }], "oldPlan" : { "cursor" : "BtreeCursor AC", "indexBounds" : { "f.14.b" : [["A", "A"]], "f.500.b" : [[10, 50]] } }, "server" : "xxxx:1234" }], "set2/xxxx:56789,yyyy:56789" : [{ "cursor" : "BtreeCursor AC", "isMultiKey" : false, "n" : 7000, "nscannedObjects" : 97692, "nscanned" : 97692, "nscannedObjectsAllPlans" : 98941, "nscannedAllPlans" : 98941, "scanAndOrder" : false, "indexOnly" : false, "nYields" : 0, "nChunkSkips" : 0, "millis" : 729, "indexBounds" : { "f.14.b" : [["A", "A"]], "f.500.b" : [[10, 50]] }, "allPlans" : [{ "cursor" : "BtreeCursor AC", "n" : 6996, "nscannedObjects" : 97692, "nscanned" : 97692, "indexBounds" : { "f.14.b" : [["A", "A"]], "f.500.b" : [[10, 50]] } }, { "cursor" : "BasicCursor", "n" : 4, "nscannedObjects" : 1249, "nscanned" : 1249, "indexBounds" : { } }], "oldPlan" : { "cursor" : "BtreeCursor AC", "indexBounds" : { "f.14.b" : [["A", "A"]], "f.500.b" : [[10, 50]] } }, "server" : "yyyy:56789" }] }, "cursor" : "BtreeCursor AC", "n" : 27799, "nChunkSkips" : 0, "nYields" : 2, "nscanned" : 390433, "nscannedAllPlans" : 393231, "nscannedObjects" : 390433, "nscannedObjectsAllPlans" : 393231, "millisShardTotal" : 3111, "millisShardAvg" : 1555, "numQueries" : 2, "numShards" : 2, "millis" : 2384 }
    
    为up相同的查询后

    解释()

    { "clusteredType" : "ParallelSort", "shards" : { "set1/xxxx:1234,yyyy:1234" : [{ "cursor" : "BtreeCursor AC", "isMultiKey" : false, "n" : 20799, "nscannedObjects" : 292741, "nscanned" : 292741, "nscannedObjectsAllPlans" : 294290, "nscannedAllPlans" : 294290, "scanAndOrder" : false, "indexOnly" : false, "nYields" : 379, "nChunkSkips" : 0, "millis" : 391470, "indexBounds" : { "f.14.b" : [["A", "A"]], "f.500.b" : [[10, 50]] }, "allPlans" : [{ "cursor" : "BtreeCursor AC", "n" : 20795, "nscannedObjects" : 292741, "nscanned" : 292741, "indexBounds" : { "f.14.b" : [["A", "A"]], "f.500.b" : [[10, 50]] } }, { "cursor" : "BasicCursor", "n" : 4, "nscannedObjects" : 1549, "nscanned" : 1549, "indexBounds" : { } }], "server" : "xxxx:1234" }], "set2/xxxx:56789,yyyy:56789" : [{ "cursor" : "BtreeCursor AC", "isMultiKey" : false, "n" : 7000, "nscannedObjects" : 97692, "nscanned" : 97692, "nscannedObjectsAllPlans" : 98941, "nscannedAllPlans" : 98941, "scanAndOrder" : false, "indexOnly" : false, "nYields" : 0, "nChunkSkips" : 0, "millis" : 910, "indexBounds" : { "f.14.b" : [["A", "A"]], "f.500.b" : [[10, 50]] }, "allPlans" : [{ "cursor" : "BtreeCursor AC", "n" : 6996, "nscannedObjects" : 97692, "nscanned" : 97692, "indexBounds" : { "f.14.b" : [["A", "A"]], "f.500.b" : [[10, 50]] } }, { "cursor" : "BasicCursor", "n" : 4, "nscannedObjects" : 1249, "nscanned" : 1249, "indexBounds" : { } }], "oldPlan" : { "cursor" : "BtreeCursor AC", "indexBounds" : { "f.14.b" : [["A", "A"]], "f.500.b" : [[10, 50]] } }, "server" : "yyyy:56789" }] }, "cursor" : "BtreeCursor AC", "n" : 27799, "nChunkSkips" : 0, "nYields" : 379, "nscanned" : 390433, "nscannedAllPlans" : 393231, "nscannedObjects" : 390433, "nscannedObjectsAllPlans" : 393231, "millisShardTotal" : 392380, "millisShardAvg" : 196190, "numQueries" : 2, "numShards" : 2, "millis" : 391486 }
    

    顺便说一下: *一个单独的upsert(一个受影响的doc)允许内存使用量下降大约600MB。 - >一些查询后才达到~4,5GB内存使用率。

    • 如果我从上面接受查询并且我使用mongoCursor在结果集上循环它只需要很长时间......(查询仍在我输入时运行):(

    更新II @Daniel

    这里有一个存储在mongoDB-Cluster中的示例文档。 碎片密钥是我的文档的 b - 属性(它对应于电话号码)

    的Upsert: 我通过分片键搜索现有文档并更新 f - 数组的一些属性。然后我在mongoDB驱动程序上逐个调用Save来保存所有这些文档(比如500k次)。

    有一个索引:{“f.14.b”:1,“f.500.b”:1} 此索引用于复杂查询。如上所述,这些查询在批量更新之前很快,在更新之后非常慢。

       {
      "_id" : ObjectId("51248d6xxxxxxxxxxxxx"),
      "b" : "33600000000",
      "f" : {
        "500" : {
          "a" : ISODate("2013-02-20T08:45:38.075Z"),
          "b" : 91
        },
        "14" : {
          "a" : ISODate("2013-02-20T08:45:38.075Z"),
          "b" : "A"
        },
        "1501" : {
          "a" : ISODate("2013-02-20T08:45:38.141Z"),
          "b" : ["X", "Y", "Z"]
        },
        "2000" : {
          "a" : ISODate("2013-02-20T08:45:38.141Z"),
          "b" : false
        }
      }
    }
    

    非常感谢, 布卢姆

2 个答案:

答案 0 :(得分:0)

  1. 你在使用什么版本的mongodb?

  2. 当您执行upsert时,可以在其上执行.explain()查看方法     它正在扫描的许多文件。

  3. upserts期间磁盘的外观是什么

答案 1 :(得分:0)

这很有趣。看起来首先,您的数据分布不均匀。您的解释显示第一组上的nscanned:292741和第二组上的nscanned:97692。差别很大。它还显示在第一组nyields:379和第二组nyields:0。这意味着只有你从你的集合中读取不均匀,你可能写不均匀。如果选择分布更均匀的分片键,您将从群集中获得更多。

至于为什么特别是这种情况发生在您的upserts上,您是否在现有文档中添加了更多数据?如果是这样,你可能是文件移动的受害者。在您的mongodb日志中,您是否看到移动的任何查询:1?这意味着日志中的慢查询也在磁盘上有文件移动,导致大量的havok与索引到数组/子文档。 Mongodb我相信如果它移动的话,仍然必须对整个文档进行索引重建,并且必须对所有索引进行大量更新到子文档/数组。

文档移动的解决方法是在创建时预先在文档上分配额外数据,然后立即将其从文档中删除。 Mongo在磁盘上分配具有固定空间+填充因子的所有文档。如果它们超出了它们的空间,它们必须在磁盘上移动到更大的区域。如果您使用已有的额外数据创建了文档,然后将其删除,您将在磁盘上为自己提供大量额外的填充以适应文档增长。这肯定会浪费空间,但它会大大提高性能。