Catatan: Jawaban ini didasarkan pada MongoDB 3.2.4.
Sebaiknya temukan penggunaan explain()
di MongoDB. explain()
keluaran kueri (mis. db.collection.explain().find(...)
) memungkinkan Anda memeriksa indeks mana yang digunakan dalam kueri, dan menggunakan db.collection.explain('executionStats')
juga akan menunjukkan kepada Anda apakah kueri berhasil atau gagal karena SORT
. dalam memori batasan.
$dalam
Sebuah $in
kueri dapat dianggap sebagai serangkaian kueri kesetaraan. Misalnya, {a: {$in: [1,3,5]}}
dapat dianggap sebagai {a:1}, {a:3}, {a:5}
. MongoDB akan mengurutkan $in
array sebelum melanjutkan dengan kueri, sehingga {$in: [3,5,1]}
tidak berbeda dengan {$in: [1,3,5]}
.
Mari kita asumsikan koleksi memiliki indeks
{a:1, b:1}
-
Mengurutkan menurut
a
db.coll.find({a: {$in: [1,3,5]}}).sort({a:1})
MongoDB akan dapat menggunakan
{a:1,b:1}
index, karena kueri ini dapat dianggap sebagai gabungan dari{a:1}, {a:3}, {a:5}
pertanyaan. Mengurutkan menurut{a:1}
memungkinkan penggunaan awalan indeks , jadi MongoDB tidak perlu melakukan pengurutan di dalam memori.Situasi yang sama juga berlaku untuk kueri:
db.coll.find({a: {$in: [1,3,5]} ,b:{$gte:1, $lt:2}}).sort({a:1})
sejak
sort({a:1})
juga menggunakan awalan indeks (a
dalam hal ini),SORT
. dalam memori panggung karena itu tidak diperlukan. -
Mengurutkan menurut
b
Ini adalah kasus yang lebih menarik dibandingkan dengan mengurutkan berdasarkan
a
. Misalnya:db.coll.find({a: {$in: [1,3,5]}}).sort({b:1})
explain()
output dari kueri ini akan memiliki tahap yang disebutSORT_MERGE
. Ingat bahwafind()
bagian dari kueri dapat dianggap sebagai{a:1}, {a:3}, {a:5}
.Kueri
db.coll.find({a:1}).sort({b:1})
tidak perlu memilikiSORT
dalam memori panggung karena sifat{a:1,b:1}
index:yaitu, MongoDB dapat dengan mudah menjalankan indeks (diurutkan) dan mengembalikan dokumen yang diurutkan berdasarkanb
setelah memenuhi parameter kesetaraan padaa
. Misalnya, untuk setiapa
, ada banyakb
yang sudah diurutkan berdasarkanb
karena indeks.Menggunakan
$in
, kueri keseluruhan dapat dianggap sebagai:db.coll.find({a:1}).sort({b:1})
db.coll.find({a:3}).sort({b:1})
db.coll.find({a:5}).sort({b:1})
- Ambil hasil kueri individual di atas, dan lakukan penggabungan menggunakan nilai
b
. Kueri tidak memerlukan tahap pengurutan dalam memori karena hasil kueri individual sudah diurutkan berdasarkanb
. MongoDB hanya perlu menggabungkan hasil sub-kueri (yang sudah diurutkan) menjadi satu hasil.
Demikian pula, kueri
db.coll.find({a: {$in: [1,3,5]} ,b:{$gte:1, $lt:2}}).sort({b:1})
juga menggunakan
SORT_MERGE
stage dan sangat mirip dengan query di atas. Perbedaannya adalah bahwa setiap kueri menghasilkan dokumen berdasarkan rentangb
(bukan setiapb
) untuk setiapa
(yang akan diurutkan berdasarkanb
karena indeks{a:1,b:1}
). Oleh karena itu, kueri tidak memerlukan tahap pengurutan dalam memori.
$atau
Untuk $or
permintaan untuk menggunakan indeks, setiap klausa di $or
ekspresi harus memiliki indeks yang terkait dengannya
. Jika persyaratan ini dipenuhi, kueri mungkin menggunakan SORT_MERGE
panggung seperti $in
pertanyaan. Misalnya:
db.coll.explain().find({$or:[{a:1},{a:3},{a:5}]}).sort({b:1})
akan memiliki rencana kueri yang hampir identik, penggunaan indeks, dan SORT_MERGE
stage seperti pada $in
contoh di atas. Pada dasarnya, kueri dapat dianggap sebagai:
db.coll.find({a:1}).sort({b:1})
db.coll.find({a:3}).sort({b:1})
db.coll.find({a:5}).sort({b:1})
- Ambil hasil kueri individual di atas, dan lakukan penggabungan menggunakan nilai
b
.
seperti $in
contoh sebelumnya.
Namun, kueri ini:
db.coll.explain().find({$or:[{a:1},{b:1}]}).sort({b:1})
tidak dapat menggunakan indeks apa pun (karena kami tidak memiliki {b:1}
indeks). Kueri ini akan menghasilkan pemindaian koleksi, dan akibatnya akan memiliki tahap pengurutan dalam memori karena tidak ada indeks yang digunakan.
Namun, jika kita membuat indeks {b:1}
, kueri akan dilanjutkan seperti:
db.coll.find({a:1}).sort({b:1})
db.coll.find({b:1}).sort({b:1})
- Ambil hasil kueri individual di atas, dan lakukan penggabungan menggunakan nilai
b
(yang sudah diurutkan di kedua sub-kueri, karena indeks{a:1,b:1}
dan{b:1}
).
dan MongoDB akan menggabungkan hasil {a:1}
dan {b:1}
kueri dan melakukan penggabungan pada hasil. Proses penggabungan adalah waktu linier, mis. O(n)
.
Kesimpulannya, dalam $or
query, setiap istilah harus memiliki indeks, termasuk sort()
panggung. Jika tidak, MongoDB harus melakukan pengurutan dalam memori.