MongoDB - 如何尽快获得字段填充率?
MongoDB - how to get fields fill-rates as quickly as possible?
我们有一个非常大的 MongoDB
文档集合,其中包含一些预定义的字段,这些字段可以有值也可以没有。
我们需要收集 fill-rates
个字段,我们编写了一个脚本遍历所有文档并计算每个文档的填充率,问题是处理所有文档需要很长时间。
有没有办法在服务器端使用db.collection.aggregate
或db.collection.mapReduce
到运行这样的脚本?
它应该有显着的性能改进吗?
它会减慢该集合的其他用途(例如持有主要锁)吗?
据我了解,您想要实现的是对您的文档进行计算,之后您就有了一个可以查询的新 "document"。您不需要存储计算的 "new values"。
如果你不需要在那个文件里面写你的"new values",你可以使用聚合框架。
聚合操作处理数据记录和return计算结果。聚合操作将来自多个文档的值分组在一起,并且可以对分组数据执行各种操作以 return 一个结果。
https://docs.mongodb.com/manual/aggregation/
由于聚合框架有很多功能,我无法为您提供有关如何解决您的问题的更多信息。
回答我自己的问题,我能够使用游标来迁移我的脚本以扫描整个集合,迁移到 map-reduce 查询,并且 运行ning 在集合的样本上似乎位于使用 map-reduce 至少快两倍。
这是旧脚本的工作方式(在 node.js 中):
var cursor = collection.find(query, projection).sort({_id: 1}).limit(limit);
var next = function() {
cursor.nextObject(function(err, doc) {
processDoc(doc, next);
});
};
next();
这是新脚本:
collection.mapReduce(
function () {
var processDoc = function(doc) {
...
};
processDoc(this);
},
function (key, values) {
return Array.sum(values)
},
{
query : query,
out: {inline: 1}
},
function (error, results) {
// print results
}
);
processDoc 基本保持不变,但我没有增加全局统计对象上的计数器,而是:
emit(field_name, 1);
运行在 100k 的样本上 ning 旧的和新的,旧的用了 20 秒,新的用了 8.
一些注意事项:
- map-reduce 的
limit
选项不适用于分片集合,我不得不查询 _id : { $gte, $lte}
以创建所需的样本大小。
- map-reduce 的性能提升选项:
jsMode : true
也不适用于分片集合(可能会进一步提高性能),它可能会 运行 它在每个分片上手动工作以获得该功能。
我们有一个非常大的 MongoDB
文档集合,其中包含一些预定义的字段,这些字段可以有值也可以没有。
我们需要收集 fill-rates
个字段,我们编写了一个脚本遍历所有文档并计算每个文档的填充率,问题是处理所有文档需要很长时间。
有没有办法在服务器端使用db.collection.aggregate
或db.collection.mapReduce
到运行这样的脚本?
它应该有显着的性能改进吗?
它会减慢该集合的其他用途(例如持有主要锁)吗?
据我了解,您想要实现的是对您的文档进行计算,之后您就有了一个可以查询的新 "document"。您不需要存储计算的 "new values"。
如果你不需要在那个文件里面写你的"new values",你可以使用聚合框架。
聚合操作处理数据记录和return计算结果。聚合操作将来自多个文档的值分组在一起,并且可以对分组数据执行各种操作以 return 一个结果。
https://docs.mongodb.com/manual/aggregation/
由于聚合框架有很多功能,我无法为您提供有关如何解决您的问题的更多信息。
回答我自己的问题,我能够使用游标来迁移我的脚本以扫描整个集合,迁移到 map-reduce 查询,并且 运行ning 在集合的样本上似乎位于使用 map-reduce 至少快两倍。
这是旧脚本的工作方式(在 node.js 中):
var cursor = collection.find(query, projection).sort({_id: 1}).limit(limit);
var next = function() {
cursor.nextObject(function(err, doc) {
processDoc(doc, next);
});
};
next();
这是新脚本:
collection.mapReduce(
function () {
var processDoc = function(doc) {
...
};
processDoc(this);
},
function (key, values) {
return Array.sum(values)
},
{
query : query,
out: {inline: 1}
},
function (error, results) {
// print results
}
);
processDoc 基本保持不变,但我没有增加全局统计对象上的计数器,而是:
emit(field_name, 1);
运行在 100k 的样本上 ning 旧的和新的,旧的用了 20 秒,新的用了 8.
一些注意事项:
- map-reduce 的
limit
选项不适用于分片集合,我不得不查询_id : { $gte, $lte}
以创建所需的样本大小。 - map-reduce 的性能提升选项:
jsMode : true
也不适用于分片集合(可能会进一步提高性能),它可能会 运行 它在每个分片上手动工作以获得该功能。