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 mongo
shell, bayangkan Anda memiliki dokumen yang terlihat seperti ini:
db.data.insert({
a: 'webscale',
b: new Array(10*1024*1024).join('z')
})
Bidang b
mungkin 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 a
dan 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 _id
nilainya. The _id
bidang termasuk dalam query hasil secara default karena merupakan pengenal unik untuk dokumen, tapi _id
tidak akan dimasukkan dalam indeks sekunder kecuali secara eksplisit menambahkan.
The totalDocsExamined
dan totalKeysExamined
metrik 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 _id
bidang 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.