MongoDB
 sql >> Teknologi Basis Data >  >> NoSQL >> MongoDB

Bagaimana cara meningkatkan kinerja operasi pembaruan di Mongo?

Saat memperbarui dengan cara Anda, Anda perlu mengambil konten dokumen untuk memeriksanya dan membuat modifikasi tersebut. MongoDB tidak memiliki operasi atomik yang bertindak berdasarkan nilai yang ada dengan cara yang Anda inginkan, jadi tentu saja diperlukan iterasi.

Tidak ada perbedaan nyata dalam bagian "permintaan" tentang cara Anda mencocokkan ekspresi reguler antara dua versi pernyataan Anda. Apa pun yang terjadi, konten dikonversi ke BSON sebelum dikirim ke server, jadi jika Anda menggunakan pembuat ekspresi standar atau dokumen BSON langsung, konsekuensinya kecil.

Tetapi pada peningkatan kinerja yang dapat dilakukan.

Gunakan Operasi Massal untuk memperbarui

Seperti yang dinyatakan, Operasi Massal adalah cara Anda harus memperbarui pada iterasi daftar tersebut, dan Anda juga "seharusnya" menggunakan kursor daripada mengonversi semua hasil ke daftar, karena akan menghemat memori.

Menghindari semua deklarasi tipe tertentu dan hanya mewakili sebagai BsonDocument ( yang mungkin akan menghemat Anda dalam menyusun, tetapi tidak diperlukan ) maka contoh proses dasarnya adalah:

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);
    }

}

Jadi daripada membuat permintaan ke database untuk setiap dokumen yang diambil dari kueri, Anda membuat List dari WriteModel operasi sebagai gantinya.

Setelah daftar ini berkembang menjadi nilai yang wajar ( 1000 dalam contoh ini ), Anda melakukan operasi tulis ke server dalam satu permintaan dan respons untuk semua operasi batch. Di sini kita menggunakan BulkWriteAsync .

Anda dapat membuat batch dalam ukuran lebih besar dari 1000 jika Anda suka, tetapi umumnya jumlah yang masuk akal untuk ditangani. Satu-satunya batas keras yang nyata adalah batas BSON 16MB, yang karena semua permintaan sebenarnya masih merupakan dokumen BSON, ini masih berlaku. Bagaimanapun dibutuhkan banyak permintaan untuk mendekati 16MB, tetapi ada juga kecocokan impedansi yang perlu dipertimbangkan dalam bagaimana permintaan akan diproses ketika benar-benar mencapai server, seperti yang didokumentasikan:

"Setiap grup operasi dapat memiliki paling banyak 1000 operasi. Jika grup melebihi batas ini, MongoDB akan membagi grup menjadi grup yang lebih kecil yang terdiri dari 1000 atau kurang. Misalnya, jika daftar operasi massal terdiri dari 2000 operasi penyisipan, MongoDB membuat 2 grup, masing-masing dengan 1000 operasi."

Oleh karena itu dengan menjaga ukuran permintaan pada tingkat yang sama dengan bagaimana server akan memprosesnya, Anda juga mendapatkan manfaat dari yield di mana "beberapa batch" sebenarnya dapat bertindak dalam koneksi paralel ke server, daripada membiarkan server melakukan pemisahan dan antrian.

Hasil yang dikembalikan adalah BulkWriteResult yang akan berisi informasi tentang jumlah "kecocokan" dan "modifikasi" dll dari kumpulan operasi yang dikirim.

Tentu saja karena operasi dalam "batch", masuk akal untuk kemudian memeriksa di akhir iterasi loop untuk melihat apakah ada operasi "batch" lagi dalam daftar, dan kemudian tentu saja mengirimkan dengan cara yang sama.

Perhatikan juga IsOrdered = false sebagai BulkWriteOptions berarti batch operasi tidak benar-benar dieksekusi dalam urutan serial, yang berarti bahwa server sebenarnya dapat menjalankan taks secara "paralel". Ini dapat membuat peningkatan kecepatan "besar" di mana urutan komitmen tidak diperlukan. Standarnya adalah mengirimkan "dipesan" dan berurutan.

Ini tidak diperlukan untuk menyetel opsi ini, tetapi jika pesanan Anda tidak penting (yang seharusnya tidak demikian dalam kasus ini karena tidak ada permintaan operasi lain di sini yang bergantung pada modifikasi dokumen sebelumnya) maka peningkatan yang Anda dapatkan bermanfaat.

Ini semua tentang "mengurangi" jumlah permintaan aktual yang dibuat ke server. Mengirim pembaruan dan menunggu tanggapan membutuhkan waktu, dan dalam operasi besar adalah latihan yang sangat mahal. Itulah yang dimaksudkan untuk ditangani oleh Operasi Massal, dengan menerapkan beberapa operasi dalam satu permintaan.

Mengurangi overhead itu adalah peningkatan kinerja "besar". Itu sebabnya Anda menggunakan ini.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Kursor MongoDB.hitung()

  2. serikat pada koleksi yang sama di mongodb

  3. Apakah ada cara untuk mencegah MongoDB menambahkan bentuk jamak ke nama koleksi?

  4. Bagaimana cara mengubah pymongo.cursor.Cursor menjadi dict?

  5. MongoDB $kisaran