【发布时间】: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