Mongodb缓慢更新循环
我刚刚熟悉Mongodb,这就是为什么我做了一些愚蠢的事情。我的每个数据集的条目都包含一个时间戳(他们是Tweets)。我没有在插入之前将时间戳从字符串转换为实际日期格式,而是将其简单插入为字符串。Mongodb缓慢更新循环
现在,我的数据集变得非常庞大(超过3百万条推文),我想开始排序/排列我的条目。由于我的时间戳仍然是一个字符串(“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
有什么想法?
默认情况下,更新阻塞,直到数据库发回确认成功执行更新为止。当您在本地工作站上使用mongo shell并连接到远程数据库时,这至少需要ping到数据库。
如果允许,可以通过SSH连接到数据库服务器(副本集的主服务器)并在其中运行脚本。这将网络延迟减少到几乎为零。当你有一个集群时,结果可能仍然是一个改进,但并不是那么多,因为你需要登录到mongos服务器,它仍然需要等待来自其更新路由的副本集的确认, 。
另一种选择是执行更新,不写入关注。程序执行将立即继续,这将大大提高速度。但请记住,这种方式会忽略任何错误。
db.ClockTime.update(
{_id : doc._id},
{$set : {ClockInTime : new Date(doc.ClockInTime)}},
{writeConcern: {w: 0}}
)
这将是更快的第三种选择是使用mongoexport
得到JSON格式的所有收藏的文件导出,与当地的脚本转换它,然后用mongoimport
重新导入的转换数据。缺点是如果在导出和导入之间没有很短的停机时间,您将无法做到这一点,因为它们之间的任何数据都将丢失。
谢谢你这个详细的答案!事实上,登录到SSH服务器的速度相当快,解决了问题,没有数据丢失,因为我不必导出/导入数据库。 – Diederik
另一种选择是使用批量操作,这是非常快的,尤其是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()
)
看看这个[文章](https://midnightcodr.github.io/2014/11/22/How-to-convert-20-million-datetime-strings-to-ISODate-in-less-比-30分钟/) – Yogesh
这似乎很有前途,谢谢! – Diederik