从Mongodb查询大列表后,Nodejs计算速度变慢

xj3cbfub  于 2022-11-03  发布在  Go
关注(0)|答案(2)|浏览(230)

我正在使用mongoose从Mongodb查询一个非常大的列表

  1. const chat_list = await chat_model.find({}).sort({uuid: 1}); // uuid is a index
  2. const msg_list = await message_model.find({}, {content: 1, xxx}).sort({create_time: 1});// create_time is a index of message collection, time: t1
  3. // chat_list length is around 2,000, msg_list length is around 90,000
  4. compute(chat_list, msg_list); // time: t2
  5. function compute(chat_list, msg_list) {
  6. for (let i = 0, len = chat_list.length; i < len; i++) {
  7. msg_list.filter(msg => msg.uuid === chat_list[i].uuid)
  8. // consistent handling for every message
  9. }
  10. }

对于上述代码,t1约为46s,t2约为150s
t2真的太大了,太奇怪了。
然后我将这些列表缓存到本地json文件中,

  1. const chat_list = require('./chat-list.json');
  2. const msg_list = require('./msg-list.json');
  3. compute(chat_list, msg_list); // time: t2

此时,t2大约为10s。
那么,问题来了,150秒对10秒,为什么?发生了什么?
我尝试使用worker在mongo查询后执行计算步骤,但时间仍然比10秒长得多

moiiocjp

moiiocjp1#

mongodb查询返回一个FindCursor,其中包含类似.filter()的数组方法,但结果不是一个Array。
在过滤之前对游标使用.toArray()来处理mongodb结果集,这可能不会使整个过程更快,因为结果集仍然需要从mongodb中提取,但计算将是类似的。

  1. const chat_list = await chat_model
  2. .find({})
  3. .sort({uuid: 1})
  4. .toArray()
  5. const msg_list = await message_model
  6. .find({}, {content: 1, xxx})
  7. .sort({create_time: 1})
  8. .toArray()
7bsow1i6

7bsow1i62#

马特打字比我快,所以建议的一些内容与这个答案的一部分一致。
我认为你在衡量和比较一些与你所期望和暗示的不同的东西。
您的期望是,一旦应用程序加载了所有数据,compute()函数大约需要10秒。(大部分)在你的第二次测试中得到了证明,除了这个测试包括从本地文件加载数据所花费的时间之外,您会看到有104秒的差异(150 - 46)之间的完成message_model.find()compute()因此导致了问题。
关键是成功地从find升级到message_model并不等同于获得所有结果。一旦第一批结果准备就绪,find()将返回一个游标对象。(显然大约94秒),这两个find()操作需要进一步迭代游标并检索其余结果。t2内部报告了额外的时间。
@Matt建议,调用.toArray()应该会将时间移回您所期望的t1。而且,由于.filter()函数的歧义性,听起来可能更正确。
还有另外两件事引起了我的注意。第一件是:为什么要在客户端检索所有这些数据并在那里进行筛选?也许您希望通过$lookup在数据库内部进行uuid匹配?
第二,这句话对我来说不太清楚:

  1. // create_time is a index of message collection, time: t1

create_time本身在这里是一个字段,无论是否存在,您都需要对其进行升序排序。

相关问题