【问题标题】:Inserting values from Meteor into MongoDB got really slow将 Meteor 中的值插入 MongoDB 变得非常慢
【发布时间】:2017-04-02 06:37:22
【问题描述】:

从 Meteor 向 MongoDB 中插入值的速度非常慢,机器没有任何负载。

  • 系统:Mac OS El Capitan
  • MongoDB 版本:2.6.12 (更新到 3.2)
  • 流星:1.4.2.3

我从 db 中获取一个值并删除 _id 以生成一个新值并将该值再次插入到 db 中。

Meteor.methods({
  testInsert() {
    const id = ID.find({ Project: Number(287), ID: Number(169372), Deleted: false }).fetch();

    if (id === undefined || id === '' || id.length > 1 || id.length === 0) {
      throw new Meteor.Error('no unique id found');
    }

    console.log('got ID ' + id[0].ID);

    const oldId = id[0]._id;
    delete id[0]._id;

    try {
      console.log('Start inserting ... ' + new Date());
      ID.insert(id[0]);
      console.log('Done inserting ' + new Date());
    } catch (e) {
      throw new Meteor.Error('error inserting`);
    }
    console.log('Done single');
  },
});

结果:

获得 ID 169372

开始插入... 2016 年 11 月 18 日星期五 12:25:59 GMT+0100 (CET)

完成插入 2016 年 11 月 18 日星期五 12:26:09 GMT+0100 (CET)

插入需要 10 秒!我插入的 JSON 大小为 14kb 或相当小。在 mongo 的 shell(命令行)中插入不到一秒钟。这段代码曾经足够快。我的桌子上也有一个索引。

ID._ensureIndex({ Deleted: 1, ID: 1 });

需要明确的是,目前任何插入都很慢,不仅仅是基于上面的示例代码。一件奇怪的事情是,运行节点/流星的机器上的负载达到 100%,对于一个简单的插入!有什么想法吗?

更新:

MongoDB 不是在我的本地开发人员机器上运行,而是在专用数据库服务器上运行,我使用隧道(如果您想知道为什么错误消息显示为 localhost :))

更新 2:

当我使用 for 循环插入 10 个 ID 流星崩溃时,虽然流星恢复它需要 5-10 分钟但它实际上写入了所有数据

Exception while polling query {"collectionName":"id","selector":{"id":287,"Deleted":false},"options":{"transform":null}}: MongoError: connection 7 to localhost:27017 timed out

更新 3:

我将 MongoDB 更新到 3.2,但仍然出现异常。

Exception while polling query {"collectionName":"ID","selector":{"ID":287,"Deleted":false},"options":{"transform":null}}: MongoError: connection 17 to localhost:27017 timed out

更新 4:

轮询错误/超时与我认为的问题无关,这就是我删除堆栈跟踪的原因。我能够构建一个通用测试用例来复制这个问题。似乎 mongo 节点/流星驱动程序无法很好地处理数组属性。我已经将带有 Java 驱动程序的条目插入到 mongo 中,没有任何问题。我创建了一个测试用例,它填充了一个包含 500 个随机条目的数组。此插入语句大约需要 10 秒。通过增加 ID 的数量,您还会遇到超时错误。

Meteor.methods({
  testInsert() {
    const testIDs = [
      { ID: 100000, array: [] },
      { ID: 200000, array: [] }];

	  function makeTestCase(id) {
	    for (let i = 0; i < 500; i += 1) {
	      id.array.push({
	        "Date": new Date,
	        "Text1" : "Lorem ipsum dolor sit amet, consectetur adipisicing elit.",
	        "Text2" : "Lorem ipsum dolor sit amet, consectetur adipisicing elit.",
	        "Text3" : "Lorem ipsum dolor sit amet, consectetur adipisicing elit.",
	        "Text4" : i,
	        "Text5" : i,
	        "Text6" : i,
	        "Text7" : i,
	      });
	    }
	  }

    testIDs.forEach(makeTestCase);

    function insertID(id) {
      try {
        console.log(`Start inserting ... ${new Date()}`);
        BshID.insert(id, { validate: false });
        console.log(`Done inserting ${new Date()}`);
      } catch (e) {
        throw new Meteor.Error('ID ERROR');
      }
    }

    testIDs.forEach(insertID);

    console.log('all done');
	}
});

【问题讨论】:

    标签: node.js mongodb performance meteor


    【解决方案1】:

    您可以做一些改进:

    ID 字段创建降序索引

    如果我正确理解了您的代码,您总是在搜索最旧的记录来生成新文档。如果您创建降序索引,MongoDB 会发现您的文档速度更快,因为它会优化您的索引以首先查看 ID 的最高值。 此外,如果您总是使用ProjectID 进行搜索,您也应该在索引中包含Project

    首先,删除最旧的索引: ID._dropIndex({Deleted: 1, ID: 1})

    然后,创建新索引:ID._ensureIndex({Deleted: 1, ID: -1, Project: -1})

    使用 findOne 代替 find

    如果您只需要一个文档,请使用findOne 查找此文档,MongoDB 无需查看您的所有记录即可获取结果。您也可以将 fields 属性添加到您的 findOne 以仅告诉 Meteor 在此操作中与您相关的字段,但看到您的示例您正在创建文档的副本,因此情况并非如此。

    ID.findOne({ 
      Project: Number(287), 
      ID: Number(169372), 
      Deleted: false 
    });
    

    额外:将您的 MongoDB 更新到 3.2

    您使用的是 Meteor 1.4,因此您应该将 MongoDB 更新到与此 Meteor 版本兼容的适当版本。更多信息请查看http://info.meteor.com/blog/announcing-meteor-1.4

    进一步阅读

    【讨论】:

    • 您好 Inmunhoz,感谢您的反应!一些澄清,是的,你是对的,我只查看最新条目,但 ID 字段不是增量 ID,因此最高值!= 最新条目,抱歉没有说清楚。使用 find 是有目的的,因为我想知道数据库中何时允许更多值。当我通过将它们的属性“deleted”设置为 false 来删除旧条目时,我有时会遇到 ID 没有得到更新,这就是我可以捕获这些的方法。
    • 关于我应该提到的MongoDB版本,我不使用meteor附带的开发人员数据库,而是使用只有MongoDB运行的专用机器上的数据库,我的期望是meteor node 的驱动程序没有限制只能使用 MongoDB > 3.2 对吗?
    • @user263367 pooling query 错误是因为您的 MongoDB 版本。当您更新到 3.2 时,它会正常工作。
    • @user263367 除了你的实现逻辑,你应该更新你的索引以在ProjectIDDeleted字段中使用升序。您当前的索引未用于获取结果,因为您的复合索引仅用于 DeletedID 字段。
    • @user263367 抱歉,我的意思是降序。
    猜你喜欢
    • 2013-12-16
    • 1970-01-01
    • 1970-01-01
    • 2019-09-29
    • 1970-01-01
    • 2023-01-17
    • 2016-12-17
    • 2017-11-01
    • 1970-01-01
    相关资源
    最近更新 更多