Bagaimana proyeksi mongoDB mempengaruhi kinerja?

10

Dari MongoDBdokumentasi disebutkan bahwa:

Saat Anda hanya membutuhkan sebagian bidang dari dokumen, Anda dapat mencapai kinerja yang lebih baik dengan mengembalikan hanya bidang yang Anda butuhkan

Bagaimana bidang pemfilteran memengaruhi kinerja? Apakah kinerja terkait dengan ukuran data yang dikirim melalui jaringan? atau ukuran data yang akan disimpan dalam memori? Bagaimana tepatnya kinerja ini ditingkatkan? Apa kinerja ini yang disebutkan dalam dokumentasi?

Saya memiliki pertanyaan MongoDB yang lambat. Apakah mengembalikan subset mempengaruhi permintaan lambat saya (saya memiliki indeks gabungan di lapangan)?

ALH
sumber
Tanpa kode, tidak mungkin menyarankan Anda. apa yang sebenarnya akan mempengaruhi kinerja dalam permintaan proyeksi "MongoDB". Itu selalu lebih baik setidaknya Anda menyebutkan kode.
Md Haidar Ali Khan
@ MdHaidarAliKhan ini bukan tentang kode dan muatan saya. Saya hanya ingin tahu mengapa mongoDB mengatakan penyaringan memengaruhi kinerja? Dari sudut pandang apa kinerja ini telah diukur? Misalnya apakah itu membantu penggunaan memori Mongo karena lebih sedikit data atau lebih sedikit IO disk (misalnya) dan sebagainya.
ALH
Saya hanya ingin tahu mengapa mongoDB mengatakan penyaringan memengaruhi kinerja? baik, Gunakan Proyeksi untuk Hanya Mengembalikan Data yang Diperlukan, maksud saya mengatakan bahwa Anda dapat mencapai kinerja yang lebih baik dengan mengembalikan hanya bidang yang Anda butuhkan. Misalnya db.posts.find ({}, {}). Sort ({}).
Md Haidar Ali Khan
, Misalnya apakah itu membantu penggunaan memori Mongo karena lebih sedikit data atau lebih sedikit IO disk (misalnya) dan sebagainya, well..bisakah Anda memperbarui versi MongoDB dan sistem operasi apa di lingkungan Anda?
Md Haidar Ali Khan
@MdHaidarAliKhan OS adalah Debian 8,MongoDB 3.6.2
ALH

Jawaban:

15

Secara default, kueri mengembalikan semua bidang dalam dokumen yang cocok. Jika Anda membutuhkan semua bidang, mengembalikan dokumen lengkap akan lebih efisien daripada meminta server memanipulasi hasil yang ditetapkan dengan kriteria proyeksi.

Namun, menggunakan proyeksi untuk membatasi bidang untuk kembali dari hasil kueri dapat meningkatkan kinerja dengan:

  • menghapus bidang yang tidak dibutuhkan dari hasil kueri (menghemat bandwidth jaringan)
  • membatasi bidang hasil untuk mencapai kueri yang dicakup (mengembalikan hasil kueri yang diindeks tanpa mengambil dokumen lengkap)

Saat menggunakan proyeksi untuk menghapus bidang yang tidak digunakan, server MongoDB harus mengambil setiap dokumen lengkap ke dalam memori (jika belum ada di sana) dan memfilter hasilnya untuk kembali. Penggunaan proyeksi ini tidak mengurangi penggunaan memori atau bekerja pada server MongoDB, tetapi dapat menghemat bandwidth jaringan yang signifikan untuk hasil kueri tergantung pada model data Anda dan bidang yang diproyeksikan.

Permintaan tertutup adalah kasus khusus di mana semua bidang yang diminta dalam hasil permintaan termasuk dalam indeks yang digunakan, sehingga server tidak harus mengambil dokumen lengkap. Kueri yang tercakup dapat meningkatkan kinerja (dengan menghindari mengambil dokumen) dan penggunaan memori (jika permintaan lain tidak mengharuskan mengambil dokumen yang sama).

Contohnya

Untuk tujuan demonstrasi melalui mongoshell, bayangkan Anda memiliki dokumen yang terlihat seperti ini:

db.data.insert({
    a: 'webscale',
    b: new Array(10*1024*1024).join('z')
})

Bidang bmungkin mewakili pemilihan nilai (atau dalam hal ini string yang sangat panjang).

Selanjutnya, buat indeks {a:1}yang merupakan bidang yang biasa digunakan ditanyakan oleh use case Anda:

db.data.createIndex({a:1})

Sederhana findOne()tanpa kriteria proyeksi mengembalikan hasil kueri sekitar 10MB:

> bsonsize(db.data.findOne({}))
10485805

Menambahkan proyeksi {a:1}akan membatasi output ke bidang adan dokumen _id(yang disertakan secara default). Server MongoDB masih memanipulasi dokumen 10MB untuk memilih dua bidang, tetapi hasil kueri sekarang hanya 33 byte:

> bsonsize(db.data.findOne({}, {a:1}))
33

Kueri ini tidak tercakup karena dokumen lengkap harus diambil untuk menemukan _idnilainya. The _idbidang termasuk dalam query hasil secara default karena merupakan pengenal unik untuk dokumen, tapi _idtidak akan dimasukkan dalam indeks sekunder kecuali secara eksplisit menambahkan.

The totalDocsExamineddan totalKeysExaminedmetrik dalam explain()hasil akan menunjukkan berapa banyak dokumen dan kunci Indeks diperiksa:

 > db.data.find(
     {a:'webscale'}, 
     {a:1}
 ).explain('executionStats').executionStats.totalDocsExamined
 > 1

Permintaan ini dapat ditingkatkan dengan menggunakan proyeksi untuk mengecualikan _idbidang dan mencapai permintaan tertutup hanya menggunakan {a:1}indeks. Permintaan yang tercakup tidak lagi perlu mengambil dokumen ~ 10MB ke dalam memori, sehingga akan efisien dalam penggunaan jaringan dan memori:

 > db.data.find(
     {a:'webscale'},
     {a:1, _id:0}
 ).explain('executionStats').executionStats.totalDocsExamined
 0

 > bsonsize(db.data.findOne( {a:'webscale'},{a:1, _id:0}))
 21

Saya memiliki pertanyaan MongoDB yang lambat. Apakah mengembalikan subset mempengaruhi permintaan lambat saya (saya memiliki indeks gabungan di lapangan)?

Ini tidak dapat dijawab tanpa konteks permintaan tertentu, contoh dokumen, dan penjelasan lengkap hasil. Namun, Anda dapat menjalankan beberapa tolok ukur di lingkungan Anda sendiri untuk kueri yang sama dengan dan tanpa proyeksi untuk membandingkan hasilnya. Jika proyeksi Anda menambahkan overhead signifikan ke keseluruhan waktu pelaksanaan kueri (memproses dan mentransfer hasil), ini mungkin petunjuk kuat bahwa model data Anda dapat ditingkatkan.

Jika tidak jelas mengapa permintaan lambat, sebaiknya mengirim pertanyaan baru dengan detail spesifik untuk diselidiki.

Stennie
sumber
1
Saya sangat menghargai penjelasan menyeluruh masalah ini. Tampaknya tidak mungkin untuk membahas pertanyaan karena respons saya memiliki lebih banyak data daripada di dalam indeks. Pertanyaan utama saya ada di sini, saya akan senang jika Anda bisa melihatnya: dba.stackexchange.com/questions/195065/…
ALH
1

Dengan proyeksi, Anda dapat mencapai situasi di mana set hasil berasal langsung dari indeks.

Jika Anda memiliki indeks gabungan di {x:1, y:1, z:1}mana tidak ada x, y, z adalah _id, Anda perlu memproyeksikan {_id:0, x:1, y:1, z:1}karena _idselalu dikembalikan sebagai bagian dari set hasil (ketika tidak diproyeksikan pergi) dan mesin perlu membaca datafile untuk mendapatkannya. Ini karena, indeks tidak memiliki nilai _id, hanya penunjuk ke dokumen tempat nilai disimpan.

JJussi
sumber
Jadi jika saya menghapus _idrespon yang dikembalikan, apakah itu sesuai dengan RAM? Apakah itu membantu?
ALH
1
MongoD (mencoba) untuk menjaga setidaknya indeks pada memori (dan sebanyak data yang cocok). Jika kueri Anda dapat diisi langsung dari indeks dan Anda memproyeksikan _id:0maka hasilnya dikembalikan sepenuhnya dari RAM, tanpa membaca data dari disk.
JJussi