2012-12-20 24 views
6

我正在使用rmongodb获取特定集合中的每个文档。它有效,但我正在处理数百万个小文件,可能有100M或更多。我使用的是由作者在网站上提出的方法:cnub.org/rmongodb.ashx使用rmongodb加速大型结果集处理

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)) 

这工作得很好成百上千的结果,但是,虽然环是非常非常慢。有什么方法可以加快速度吗?也许是多处理的机会?任何建议,将不胜感激。我每小时的平均值为1M,按照这个速度,我只需要一个星期来构建数据框。

编辑: 我注意到while循环中的矢量越多,它越慢。我现在试图分别为每个向量循环。尽管如此,仍然看起来像一个黑客,必须有更好的方法。

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

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")) 

}

+0

我不是r程序员,事实上我从来没有使用过它,但是为什么你不选择你需要的数据的子集,而不是迭代整个集合,然后执行所需的验证?在这种情况下,发送像6个游标服务器端而不是仅仅一个会更容易。 – Sammaye

+0

咦?当然,while循环中的矢量越多,它越慢。还有更多的事情要做。所以需要更长的时间。或者它是非线性的?它是如何表现你正在循环的事物数量的不同值?或者,“更多媒介”是否意味着更多的东西,如年龄和名字?不清楚。 – Spacedman

+0

@Sammaye,这正是我的意思是分别为每个向量循环。我昨晚试了一次,在这个循环中放了一个计数器,它似乎刚刚死亡,几个小时后停止打印。 rsession只是挂起。所以这种方法没有帮助。 – rjb101

回答

3

你可能想尝试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可能是您想要的。这可能值得驱动程序开发人员寻求建议。

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

+0

我不能找到关于mongo.find.exhaust如何提高速度的任何解释。你知道它是如何工作的吗? – user1176316

+0

我有限的理解是它强制一次检索所有查询匹配。如果从cursor.next到数据库重复调用的开销很大,它可以提高速度。实际上,在这个用例中,我只给出3%的机会,但这是一个简单的改变,值得一试。我最好的参考是http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#find – mjhm

1

我知道没有更快的方式来以一般的方式做到这一点。您正在从外部应用程序导入数据并使用解释型语言,并且rmongodb无法预测该集合中文档的结构。当你处理数以千计的文档时,这个过程本身就很慢。

+1

谢谢杰拉德。这些文档对mongo.find.exhaust有点亮,你能详细说明一下吗?我添加了这个选项,R崩溃了。 – rjb101

+0

问题在于每次都附加i = i + 1。我认为R每次都在复制数据结构,然后将其替换,所以它越大,越差。这与解释型语言无关,因为在Python中速度要快几个数量级。 –