Mongodb缓慢更新循环

时间:2015-05-04 10:13:59

标签: mongodb

我只是熟悉Mongodb,这就是为什么我做了一些愚蠢的事情。我的每个数据集的条目都包含一个时间戳(它们是推文)。我没有在插入之前将时间戳从字符串转换为实际的日期格式,而是将其简单地插入为字符串。

现在,我的数据集变得越来越庞大(超过300万条推文),我想开始对我的条目进行排序/测距。由于我的时间戳仍然是一个字符串(“Wed Apr 29 09:52:22 +0000 2015”),我想将其转换为日期格式。

我在这个答案中找到了以下代码: How do I convert a property in MongoDB from text to date type?

> var cursor = db.ClockTime.find()
> while (cursor.hasNext()) {
... var doc = cursor.next();
... db.ClockTime.update({_id : doc._id}, {$set : {ClockInTime : new Date(doc.ClockInTime)}})
... }

它很棒。然而,它非常缓慢。根据MongoHub应用程序,它每秒只处理4个查询。使用300多万条推文的数据集,转换大约需要8.6天。我真的希望有一种方法可以加快速度,因为我的截止日期是8天:P

有什么想法吗?

2 个答案:

答案 0 :(得分:8)

另一种选择是使用非常快的批量操作,尤其是the unordered variant,因为它们可以并行应用。

var bulk = db.ClockTime.initializeUnorderedBulkOp()
var myDocs = db.ClockTime.find()
var ops = 0

myDocs.forEach(
  function(myDoc) {
    bulk.find(
      {_id:myDoc._id}
    ).updateOne(
        {$set : { ClockInTime: new Date(myDoc.ClockInTime) } }
    );

    if ( (++ops % 10000) === 0){
      bulk.execute();
      bulk = db.ClockTime.initializeUnorderedBulkOp();
    }
  }
)

bulk.execute()

答案 1 :(得分:6)

默认情况下,更新会阻止,直到数据库发回确认它已成功执行更新。当您在本地工作站上使用mongo shell并连接到远程数据库时,这将至少与您对数据库的ping一样长。

当您被允许这样做时,您可以通过SSH连接到数据库服务器(副本集的主服务器)并在那里运行脚本。这将网络延迟降低到几乎为零。当你有一个集群时,结果可能仍然是一个改进,但不是那么多,因为你需要登录mongos服务器,它仍然需要等待来自它将更新路由到的副本集的确认。

另一种选择是在没有写入问题的情况下执行更新。然后程序执行将立即继续,这将大大提高速度。但请记住,这样会忽略任何错误。

db.ClockTime.update(
    {_id : doc._id}, 
    {$set : {ClockInTime : new Date(doc.ClockInTime)}},
    {writeConcern: {w: 0}}
)

更快的第三个选项是使用mongoexport以JSON格式导出整个集合的文件,使用本地脚本进行转换,然后使用mongoimport重新创建 - 导入转换后的数据。缺点是如果没有导出和导入之间的短暂停机时间,您将无法执行此操作,因为介于两者之间的任何数据都将丢失。