現在の方法で更新する場合は、ドキュメントの内容を調べて変更するために、ドキュメントの内容を取得する必要があります。 MongoDBには、既存の値に希望どおりに作用するアトミック操作がないため、もちろん反復が必要です。
2つのバージョンのステートメント間で、正規表現の照合方法の「クエリ」部分に実際の違いはありません。いずれにせよ、コンテンツはサーバーに送信する前にBSONに変換されるため、標準の式ビルダーまたは直接のBSONドキュメントを使用してもほとんど影響はありません。
しかし、実行可能なパフォーマンスの向上についてです。
一括操作を使用して更新する
前述のように、一括操作は、このようなリストの反復で更新する必要がある方法です。また、すべての結果をリストに変換するのではなく、カーソルを使用する必要があります。これにより、メモリが節約されます。
すべての特定の型宣言を避け、BsonDocument
として表すだけです。 (これにより、マーシャリングを節約できますが、必須ではありません)、基本的なプロセス例は次のようになります。
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);
}
}
したがって、クエリから取得したすべてのドキュメントについてデータベースにリクエストを送信するのではなく、List
を作成します。 WriteModel
の 代わりに操作します。
このリストが妥当な値(この例では1000)に成長したら、すべてのバッチ操作に対する単一の要求と応答でサーバーへの書き込み操作をコミットします。ここではBulkWriteAsync
を使用します 。
必要に応じて、1000を超えるサイズでバッチを作成できますが、通常は、処理するのに妥当な数です。唯一の実際のハード制限は16MBのBSON制限です。これは、すべてのリクエストが実際にはBSONドキュメントであるため、これが引き続き適用されます。とにかく、16MBに近づくには多くのリクエストが必要ですが、文書化されているように、リクエストが実際にサーバーに到達したときにリクエストがどのように処理されるかを考慮するためのインピーダンス一致もあります。
"各操作グループは最大1000の操作を持つことができます。グループがこの制限を超えると、MongoDBはグループを1000以下の小さなグループに分割します。たとえば、一括操作リストが2000の挿入操作で構成されている場合、MongoDBそれぞれ1000回の操作で2つのグループを作成します。」
したがって、リクエストサイズをサーバーが処理する方法と同じレベルに保つことで、yield
のメリットも得られます。 ここで、「複数のバッチ」は、サーバーに分割とキューイングを行わせるのではなく、実際にはサーバーへの並列接続で機能する可能性があります。
返される結果はBulkWriteResult
です。 これには、送信された一連の操作からの「一致」や「変更」などの数に関する情報が含まれます。
当然、操作は「バッチ」で行われるため、ループの反復の最後に、リストに「バッチ」された操作が他に存在するかどうかを確認してから、もちろん同じ方法で送信するのが理にかなっています。
>
IsOrdered = false
にも注意してください BulkWriteOptions
として これは、操作のバッチが実際にはシリアル順に実行されないことを意味します。つまり、サーバーは実際に「並列」でタックを実行できます。これにより、コミットメントの順序が不要な場合に「大幅な」速度の向上を実現できます。デフォルトでは、「注文済み」でシリアルに送信されます。
このオプションを設定するためにこれは必須ではありませんが、注文が重要でない場合(ここでの他の操作要求はドキュメントの以前の変更に依存しないため、この場合は重要ではありません)、得られる改善は価値があります。
これは、サーバーに対して行われる実際の要求の数を「減らす」ことです。更新の送信と応答の待機には時間がかかり、大規模な操作では非常にコストのかかる作業になります。これが、1つのリクエスト内で複数の操作を適用することで一括操作が処理することを目的としています。
そのオーバーヘッドを減らすことは、「巨大な」パフォーマンスの向上です。これを使用するのはそのためです。