2

我正在测试 MongoDB 上的分片,因为我的集合子集正在迅速增长,并正在寻找一种加快查询速度的方法。就像分片的想法一样,能够在单个查询上使用多个线程来加速它。

现在我发现,当你启用分片,或者实际上将一个 shardkey 添加到集合中时,查询响应时间显着增加了40%to 100%,只有当查询是在 mongos 而不是 mongod 上完成时。得到了一致的结果,所以我设置了一个测试,也许你可以帮助我找出为什么它变慢以及我做错了什么,或者它是否是 Mongo 分片的一个令人讨厌的错误/问题。

  1. 启动一个空的配置服务器
  2. 启动一个空的 mongod
  3. 启动 mongos
  4. 连接到 mongos
  5. 使用测试数据库
  6. 添加数据:for(var i = 0; i < 200000; i++) { db.testcol.insert({field1: i}); }
  7. 添加索引:db.testcol.ensureIndex({field1:1})
  8. 测试查询速度几次:db.testcol.find({field1:{$gte: 0}}).explain(); 在我的测试系统上,我得到了一致的300 ms
  9. 启用分片:sh.enableSharding("testdb.testcol");
  10. 测试查询速度:仍然300 ms
  11. 碎片收集:sh.shardCollection("testdb.testcol", {field1:1})
  12. 再次测试查询速度几次:现在我得到了一致的660 ms响应时间!!!!这里发生了什么?我得到完全相同的结果集,但现在响应时间显着增加。一切都是本地主机。

  13. 现在直接连接mongod

  14. use testdb
  15. 使用相同的查询进行测试:db.testcol.find({field1:{$gte: 0}}).explain(); 您将看到 300 毫秒的响应时间。因此,通过 mongos 对集合进行分片后,响应时间会显着增加。您需要 2 台机器才能获得与分片之前相同的响应时间。这不应该是正确分片的想法,还是我在这里遗漏了一点,而不仅仅是传播数据而不是提高性能?

补充: 1. 用不同的块大小测试它,1块,1000块。对响应时间没有影响 2. 监控 CPU 使用率并且所有 CPU 都在 mongod 上完成,mongos 不做任何事情。看起来当 mongod 查询一个分片集合(来自 mongos 的查询)时,与直接在 mongod 上执行的同一集合上的查询相比,它具有很大的 CPU。3. 嗅探查询,但是从 mongos 到 mongod 的查询在分片前和分片后是相同的。

  1. 另一个有趣的发现!看看下面的过程:

mongos> db.testcol.find({field1: {$gte: 0}},{_id:0,field1:1}).explain(); { "cursor" : "BtreeCursor field1_1", "isMultiKey" : false, "n" : 5000000, "nscannedObjects" : 0, "nscanned" : 5000000, "nscannedObjectsAllPlans" : 0, "nscannedAllPlans" : 5000000, "scanAndOrder" : false, "indexOnly" : true, "nYields" : 6, "nChunkSkips" : 0, "millis" : 4660, "indexBounds" : { "field1" : [ [ 0, 1.7976931348623157e+308 ] ] }, "server" : "jvangaalen-PC:27020", "millis" : 4660 } mongos> sh.shardCollection("testdb.testcol",{field1:1}); { "collectionsharded" : "testdb.testcol", "ok" : 1 } mongos> db.testcol.find({field1: {$gte: 0}},{_id:0,field1:1}).explain(); { "clusteredType" : "ParallelSort", "shards" : { "192.168.11.250:27020" : [ { "cursor" : "BtreeCursor field1_1", "isMultiKey" : false, "n" : 5000000, "nscannedObjects" : 5000000, "nscanned" : 5000000, "nscannedObjectsAllPlans" : 5000000, "nscannedAllPlans" : 5000000, "scanAndOrder" : false, "indexOnly" : true, "nYields" : 10, "nChunkSkips" : 0, "millis" : 9378, "indexBounds" : { "field1" : [ [ 0, 1.7976931348623157e+308 ] ] }, "server" : "jvangaalen-PC:27020" } ] }, "cursor" : "BtreeCursor field1_1", "n" : 5000000, "nChunkSkips" : 0, "nYields" : 10, "nscanned" : 5000000, "nscannedAllPlans" : 5000000, "nscannedObjects" : 5000000, "nscannedObjectsAllPlans" : 5000000, "millisShardTotal" : 9378, "millisShardAvg" : 9378, "numQueries" : 1, "numShards" : 1, "indexBounds" : { "field1" : [ [ 0, 1.7976931348623157e+308 ] ] }, "millis" : 9426 }

分片前:4660 ms响应时间。分片后:9426 ms响应时间。

索引的使用方式相同。一个区别是nscannedobjectswhich was0和 now 是5000000(所有文档)。为什么nscannedobjects不是0分片后?这可能是额外 CPU 的原因

4

0 回答 0