3

我对 mongoDB 比较陌生。我建立了一个带有2 个副本集的 shard mongo 集群;每个集合在一个分片中。-> 4个mongo恶魔

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

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

如果我只执行几个更新查询,我的内存使用量就会大幅下降......就像 mongo 立即释放 3GB 的 RAM并且如此快速的读取查询变得非常慢。

如果我连续启动 500k upserts(保存),情况会变得更糟。 一个需要 2 秒才能运行的复杂查询现在需要 22 分钟。

对于具有相同查询参数的计数查询,我得到相同的行为。

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

---更新@hwatkins

  1. MongoDB版本:2.2.2
  2. 为单个 upsert 扫描 1 个文档
  3. 我在批量更新期间有相当高的磁盘活动

explain() 用于在 upsert 之前进行复杂的计数查询

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 }

对同一查询进行 upsert 后的 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" : 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(一个受影响的文档)让内存使用量下降了大约 600MB。--> ~ 4,5GB 内存使用仅在一些查询后达到。

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

更新二@丹尼尔

在这里,您获得了存储在 mongoDB-Cluster 中的示例文档。 Shard Key是我的文档的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
    }
  }
}

非常感谢,布鲁姆

4

2 回答 2

0
  1. 你用的是什么版本的mongodb?

  2. 当您执行 upsert 时,您可以对其进行操作.explain()以查看它正在扫描多少文档。

  3. 在 upserts 期间磁盘 io 是什么样的
于 2013-03-01T14:47:15.813 回答
0

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

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

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

于 2013-03-06T19:25:22.263 回答