C# 如何提高Mongo中更新操作的性能? foreach(wait records.Find(filter.ToListAsync()中的var doc) { var query=Builders.Filter.Eq(“JobTypeValue”,doc.JobTypeValue); var updatedJobInfo=Regex.Replace(doc.SerializedBackgroundJobInfo,pattern,“”); var update=Builders.update.Set(“SerializedBackgroundJobInfo”,updatedJobInfo); records.UpdateOneAsync(查询,更新).Wait(); }

C# 如何提高Mongo中更新操作的性能? foreach(wait records.Find(filter.ToListAsync()中的var doc) { var query=Builders.Filter.Eq(“JobTypeValue”,doc.JobTypeValue); var updatedJobInfo=Regex.Replace(doc.SerializedBackgroundJobInfo,pattern,“”); var update=Builders.update.Set(“SerializedBackgroundJobInfo”,updatedJobInfo); records.UpdateOneAsync(查询,更新).Wait(); },c#,mongodb,performance,C#,Mongodb,Performance,这是更新文档的最佳方式吗(我将名称中包含密码的xml字符串中的标记值更改为空标记:​)?我正在使用Mongo驱动程序2.0.2 我收集了一批500000文档,其中我每分钟(希望)会更新约3000份 如何提高更新操作的性能?以您现在的方式更新时,您需要检索文档内容,以便检查文档内容并进行此类修改。MongoDB没有以您希望的方式作用于现有值的原子操作,因此当然需要迭代 在语句的两个版本之间,如何匹配正则表达式的“查询”部分没有真正的区别。无论如何,内容在发送到服务器之前都会转换为BSON,因此如果

这是更新文档的最佳方式吗(我将名称中包含
密码
的xml字符串中的标记值更改为空标记:​<代码>)?我正在使用Mongo驱动程序2.0.2

我收集了一批
500000
文档,其中我每分钟(希望)会更新约3000份


如何提高
更新
操作的性能?

以您现在的方式更新时,您需要检索文档内容,以便检查文档内容并进行此类修改。MongoDB没有以您希望的方式作用于现有值的原子操作,因此当然需要迭代

在语句的两个版本之间,如何匹配正则表达式的“查询”部分没有真正的区别。无论如何,内容在发送到服务器之前都会转换为BSON,因此如果使用标准的expression builder或直接的BSON文档,则影响不大

但是,我们必须继续关注可以进行的性能改进

使用批量操作更新
如前所述,批量操作是您应该在此类列表迭代中进行更新的方式,而且您还“应该”使用游标,而不是将所有结果转换为列表,因为这样可以节省内存

避开所有特定的类型声明,仅表示为
BsonDocument
(这可能会节省编组,但不是必需的),那么基本示例流程将是:

foreach (var doc in await records.Find(filter).ToListAsync())
{
    var query = Builders<JobInfoRecord>.Filter.Eq("JobTypeValue", doc.JobTypeValue);
    var updatedJobInfo = Regex.Replace(doc.SerializedBackgroundJobInfo, pattern, "<$1></$1>");
    var update = Builders<JobInfoRecord>.Update.Set("SerializedBackgroundJobInfo", updatedJobInfo);

    records.UpdateOneAsync(query, update).Wait();
}

var模式=@“(si)那么,如果不是BSON,您认为正则表达式是如何应用的呢?换句话说,当它们向服务器发送请求时,两个表达式实际上是完全相同的。
RegexReplace
当然是完全不同的事情,因为这只能在客户端发生。但是您应该使用“bulkWrite”“而不是任何形式的
UpdateOne
,因为您可以在一次请求中发送1000,而不是一次发送等待一次响应,在一个循环中一遍又一遍。你能告诉我如何使用
bulkWrite
而不是
UpdateOneAsync
?为什么它会更快?你的意思是我需要在构建器中使用
JobInfoRecord
而不是
BsonDocument
?Anatoly它是可互换的,或者至少应该是这样,所以你应该能够使用这两种方法。但我的实际陈述正好相反,因为在我看来,从BSON到特定成本的mashalling中存在“成本”。因此,为了实现“快速迭代”,我怀疑至少在“游标”迭代器(可能在其他地方)中的
BsonDocument
会为您节省一些CPU周期。像这样的事情在大列表上累加起来。为什么在
if(ops.Count==1000)
中选择
1000
元素?“你对这个号码有什么建议吗?”安纳托利在答案的正文中补充了解释。
var pattern = @"(?si)<([^\s<]*workUnit[^\s<]*)>.*?</\1>";
var filter = Builders<JobInfoRecord>.Filter.Regex(x => x.SerializedBackgroundJobInfo,
                                              new BsonRegularExpression(pattern, "i"));


var ops = new List<WriteModel<BsonDocument>>();
var writeOptions = new BulkWriteOptions() { IsOrdered = false };

using ( var cursor = await records.FindAsync<BsonDocument>(filter))
{
    while ( await cursor.MoveNextAsync())
    {
        foreach( var doc in cursor.Current )
        {
            // Replace inspected value
            var updatedJobInfo = Regex.Replace(doc.SerializedBackgroundJobInfo, pattern, "<$1></$1>");

            // Add WriteModel to list
            ops.Add(
                new UpdateOneModel<BsonDocument>(
                    Builders<BsonDocument>.Filter.Eq("JobTypeValue", doc.JobTypeValue),
                    Builders<BsonDocument>.Update.Set("SerializedBackgroundJobInfo", updatedJobInfo)
                )
            );

            // Execute once in every 1000 and clear list
            if (ops.Count == 1000)
            {
                BulkWriteResult<BsonDocument> result = await records.BulkWriteAsync(ops,writeOptions);
                ops = new List<WriteModel<BsonDocument>>();
            }
        }
    }

    // Clear any remaining
    if (ops.Count > 0 )
    {
        BulkWriteResult<BsonDocument> result = await records.BulkWriteAsync(ops,writeOptions);
    }

}