【问题标题】:speed up large result set processing using rmongodb使用 rmongodb 加速大型结果集处理
【发布时间】:2012-12-07 13:33:59
【问题描述】:

我正在使用 rmongodb 来获取特定集合中的每个文档。它可以工作,但我正在处理数百万个小文档,可能是 100M 或更多。我正在使用作者在网站上建议的方法:cnub.org/rmongodb.ashx

count <- mongo.count(mongo, ns, query)
cursor <- mongo.find(mongo, query)
name <- vector("character", count)
age <- vector("numeric", count)
i <- 1
while (mongo.cursor.next(cursor)) {
    b <- mongo.cursor.value(cursor)
    name[i] <- mongo.bson.value(b, "name")
    age[i] <- mongo.bson.value(b, "age")
    i <- i + 1
}
df <- as.data.frame(list(name=name, age=age))

这适用于数百或数千个结果,但 while 循环非常非常慢。有什么方法可以加快速度吗?也许是多处理的机会?任何建议,将不胜感激。我平均每小时 100 万,按照这个速度,我需要一周的时间来构建数据框。

编辑: 我注意到while循环中的向量越多,它变得越慢。我现在尝试为每个向量分别循环。虽然看起来仍然像一个 hack,但一定有更好的方法。

编辑 2: 我对 data.table 有一些运气。它仍在运行,但看起来它将在 4 小时内完成 12M(这是我当前的测试集),这是一个进步,但远非理想

dt <- data.table(uri=rep("NA",count),
                 time=rep(0,count),
                 action=rep("NA",count),
                 bytes=rep(0,count),
                 dur=rep(0,count))

while (mongo.cursor.next(cursor)) {
  b <- mongo.cursor.value(cursor)
  set(dt, i, 1L,  mongo.bson.value(b, "cache"))
  set(dt, i, 2L,  mongo.bson.value(b, "path"))
  set(dt, i, 3L,  mongo.bson.value(b, "time"))
  set(dt, i, 4L,  mongo.bson.value(b, "bytes"))
  set(dt, i, 5L,  mongo.bson.value(b, "elaps"))

}

【问题讨论】:

  • 我不是程序员,事实上我从来没有使用过它,但是你为什么不挑选出你需要的数据子集,而不是仅仅遍历整个集合然后执行所需的验证呢?在这种情况下,在服务器端发送 6 个游标而不是只发送一个会更快。
  • 嗯?当然,while 循环中的向量越多,它变得越慢。还有更多事情要做。所以需要更长的时间。还是非线性的?它在您循环的事物数量的不同值下表现如何?或者“更多向量”是指更多诸如年龄和姓名之类的东西?不清楚。
  • @Sammaye,这正是我为每个向量分别循环的意思。我昨晚试过了,在那个循环中放了一个计数器,它似乎刚刚死了,几个小时后它就停止了打印。 rsession 刚刚挂起。所以这个方法没有用。
  • 您应该能够为测试目的进行子集化。另一个想法——用 Python 或其他语言做这个简单的循环不应该花费太多精力——这可能会告诉你它的 R 或你的 MongoDB 性能。
  • 您可以考虑为 mongodb 编写一个查询,将整个结果集输出到 csv。然后在一次调用中将该 csv 加载到 R 中。也就是说,使用单个写入/读取文件/IO 设计,而不是 R 中直接与 mongodb 对话的 while 循环。或者,如果您可以矢量化 while 循环(即删除 while 调用),您可以直接从 R 实现快速调用。如果您设法在 R 中实现这一点,我会很感兴趣。

标签: r mongodb dataframe rmongodb bigdata


【解决方案1】:

我不知道以一般方式执行此操作的更快方法。您正在从外部应用程序导入数据并使用解释语言,rmongodb 无法预测集合中文档的结构。当您处理数以千计的文档时,这个过程本身就很慢。

【讨论】:

  • 谢谢杰拉德。这些文档对 mongo.find.exhaust 有点轻,你能详细说明一下吗?我添加了这个选项,R 崩溃了。
  • 问题出在每次 i = i + 1 的追加中。我相信 R 每次都在复制数据结构然后替换它,所以它变得越大,它变得越糟。它与解释语言无关,因为在 Python 中这要快几个数量级。
【解决方案2】:

您可能想尝试mongo.find.exhaust 选项

cursor <- mongo.find(mongo, query, options=[mongo.find.exhaust])

如果确实适用于您的用例,这将是最简单的解决方法。

但是 rmongodb 驱动程序似乎缺少其他驱动程序上可用的一些额外功能。例如,JavaScript 驱动程序有一个Cursor.toArray 方法。它直接将所有查找结果转储到数组中。 R 驱动程序有一个mongo.bson.to.list 函数,但mongo.cursor.to.list 可能是您想要的。可能值得向驱动程序开发人员寻求建议。

一个 hacky 解决方案可能是创建一个新集合,其文档是每个原始文档的 100000 个数据“块”。然后可以使用mongo.bson.to.list 有效地读取这些中的每一个。可以使用 mongo 服务器 MapReduce 功能构建分块集合。

【讨论】:

  • 我找不到任何关于 mongo.find.exhaust 如何提高速度的解释。你知道它实际上是如何工作的吗?
  • 我的有限理解是它强制一次检索所有查询匹配项。如果从 cursor.next 到数据库的重复调用开销很大,它可以提高速度。我只会给它 3% 的机会在这个用例中实际提供帮助,但这是一个简单的改变,所以值得一试。我最好的参考是mongodb.github.com/node-mongodb-native/api-generated/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-31
  • 2014-07-11
  • 2016-07-22
相关资源
最近更新 更多