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

Bagaimana cara kerja pengurutan dengan kueri `$or` dan `$in` di MongoDB?

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 disebut SORT_MERGE . Ingat bahwa find() bagian dari kueri dapat dianggap sebagai {a:1}, {a:3}, {a:5} .

    Kueri db.coll.find({a:1}).sort({b:1}) tidak perlu memiliki SORT dalam memori panggung karena sifat {a:1,b:1} index:yaitu, MongoDB dapat dengan mudah menjalankan indeks (diurutkan) dan mengembalikan dokumen yang diurutkan berdasarkan b setelah memenuhi parameter kesetaraan pada a . Misalnya, untuk setiap a , ada banyak b yang sudah diurutkan berdasarkan b 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 berdasarkan b . 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 rentang b (bukan setiap b ) untuk setiap a (yang akan diurutkan berdasarkan b 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.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Gunakan LIKE/regex dengan variabel di mongoid

  2. Hitung Dot Product antara dua array dengan MongoDB Aggregate

  3. bagaimana cara memeriksa apakah mongodb sudah aktif dan siap menerima koneksi dari skrip bash?

  4. MongooseError:Anda tidak dapat `mongoose.connect()` beberapa kali saat terhubung

  5. Peningkatan kinerja menggunakan UUID alih-alih representasi string sebagai _id di MongoDB?