All Products
Search
Document Center

ApsaraDB for MongoDB:Rencana kueri dan replanning kueri

Last Updated:Mar 27, 2026

Topik ini menjelaskan cara kerja query planner MongoDB, bagaimana rencana kueri di-cache dan dievaluasi, serta penyebab terjadinya replanning kueri. Topik ini juga mencakup cara mengidentifikasi masalah replanning dan solusi yang tersedia.

Query planner

Untuk kueri tertentu, query planner MongoDB memilih dan menyimpan cache rencana kueri yang paling efisien berdasarkan indeks yang tersedia. Gambar berikut menunjukkan cara kerja query planner.

image

Evaluasi rencana kueri yang paling efisien didasarkan pada jumlah unit kerja (works) yang dilakukan oleh rencana eksekusi kueri saat query planner mengevaluasi rencana kandidat. Entri cache rencana dapat digunakan kembali oleh kueri berikutnya yang memiliki bentuk kueri (query shape) yang sama.

Status entri cache rencana

Entri cache rencana dapat berada dalam salah satu status berikut:

State Description
Missing Tidak ada entri dalam cache rencana. Query planner harus mengevaluasi rencana kandidat dari awal.
Inactive Terdapat entri dalam cache rencana dengan nilai works yang direkam dari evaluasi sebelumnya. Entri ini dapat berpindah ke status Active.
Active Terdapat entri dalam cache rencana dan digunakan untuk kueri yang sesuai. Rencana pemenang dalam status Active dapat kembali ke status Inactive jika tidak lagi efisien.

Perilaku cache rencana

Cache rencana disimpan sepenuhnya dalam memori dan tidak bertahan setelah restart. Cache ini dihapus dalam situasi berikut:

  • Database MongoDB di-restart.

  • Koleksi atau indeks dihapus.

Cache rencana juga memiliki batas ukuran dan mengikuti mekanisme penggantian cache least recently used (LRU). Entri yang lebih jarang diakses akan dikeluarkan dari cache seiring waktu.

Perintah manajemen cache rencana

Anda dapat menjalankan perintah berikut untuk mengelola entri cache rencana untuk koleksi tertentu:

Command Description
db.<collection>.getPlanCache().clear() Menghapus cache rencana untuk suatu koleksi.
db.<collection>.getPlanCache().listQueryShapes() Menampilkan semua bentuk kueri dalam cache rencana untuk suatu koleksi.
db.<collection>.getPlanCache().getPlansByQuery(...) Mengambil rencana kueri yang di-cache untuk kueri tertentu.

Contoh pengambilan rencana kueri yang di-cache:

db.<collection>.getPlanCache().getPlansByQuery({"query": {"name": "testname"}, "sort": { "name": 1 })

queryHash dan planCacheKey

MongoDB 4.2 dan versi yang lebih baru memperkenalkan queryHash untuk mengidentifikasi bentuk kueri. Setiap bentuk kueri dikaitkan dengan nilai queryHash. MongoDB 4.2 juga memperkenalkan planCacheKey, yang berbeda dari queryHash karena merupakan fungsi dari bentuk kueri dan indeks yang tersedia untuk bentuk tersebut. Jika indeks yang mendukung bentuk kueri dibuat atau dihapus, nilai planCacheKey dapat berubah, tetapi nilai queryHash tetap tidak berubah.

Contoh

Pertimbangkan koleksi dengan indeks dan bentuk kueri berikut:

Indeks:

db.foo.createIndex( { x: 1 } )
db.foo.createIndex( { x: 1, y: 1 } )
db.foo.createIndex( { x: 1, z: 1 }, { partialFilterExpression: { x: { $gt: 10 } } } )

Bentuk kueri:

db.foo.explain().find( { x: { $gt: 5 } } ) // Operasi kueri 1
db.foo.explain().find( { x: { $gt: 20 } } ) // Operasi kueri 2

Indeks ketiga menggunakan ekspresi filter parsial yang mensyaratkan x > 10. Oleh karena itu, indeks ini dapat mendukung operasi kueri 2 (x > 20) tetapi tidak operasi kueri 1 (x > 5). Akibatnya, kedua kueri memiliki nilai planCacheKey yang berbeda. Jika indeks baru {x:1, a:1} dibuat, nilai planCacheKey untuk kedua operasi kueri akan berubah.

Replanning kueri

Ketika data dalam koleksi berubah secara signifikan, rencana kueri yang sebelumnya di-cache mungkin tidak lagi optimal. Query planner mendeteksi hal ini dan mengganti rencana tersebut untuk mempertahankan efisiensi kueri.

Saat Anda menjalankan kueri yang sesuai dengan bentuk kueri dari rencana yang di-cache, query planner langsung menggunakan rencana yang di-cache tanpa mengevaluasi ulang rencana kandidat. Namun, query planner terus memantau efisiensi eksekusi rencana yang di-cache. Jika rencana yang di-cache memerlukan lebih dari 10 kali jumlah unit kerja yang diharapkan, query planner akan menghapus rencana yang di-cache tersebut dan mengevaluasi ulang semua rencana kandidat. Proses ini disebut replanning kueri.

Dampak

  • Replanning kueri yang sering dapat menurunkan performa kueri.

  • Replanning kueri yang berlebihan dapat menyebabkan contention pada mutex lock, sehingga mengakibatkan tingginya utilisasi CPU.

Mengidentifikasi replanning

Anda mungkin menemukan kata kunci "replanned":true dalam log kueri lambat. Kata kunci ini menunjukkan bahwa query planner tidak dapat mempertahankan rencana yang konsisten efisien untuk bentuk kueri tertentu.

Contoh entri log kueri lambat:

"replanned":true,"replanReason":"cached plan was less efficient than expected: expected trial execution to take X works but it took at least 10X works"

Solusi

Solusi berikut diurutkan dari perbaikan jangka panjang yang direkomendasikan hingga mitigasi segera dan langkah darurat terakhir.

Direkomendasikan: optimalkan kueri dan indeks

Optimalkan pernyataan kueri Anda dan buat indeks yang efektif untuk mencegah replanning kueri. Tinjau dan sesuaikan kueri, indeks yang tersedia, serta pola dokumen Anda alih-alih mengandalkan hint atau filter indeks.

Catatan

Ini adalah pendekatan yang disarankan karena mengatasi akar penyebab replanning, bukan hanya mengatasinya secara sementara.

Direkomendasikan: upgrade versi MongoDB

Jika versi utama instans Anda adalah MongoDB 4.2 atau MongoDB 4.4, perbarui versi minor ke versi terbaru yang tersedia. Hal ini dapat secara signifikan mengurangi contention pada mutex lock. Anda juga dapat melakukan upgrade versi utama ke 5.0 atau 6.0 untuk mengatasi masalah ini. Untuk informasi lebih lanjut mengenai perbaikan kernel terkait, lihat SERVER-40805.

Untuk petunjuk upgrade, lihat Update the minor version of an instance dan Upgrade the major version of an instance.

Hapus cache rencana

Hapus cache rencana dan biarkan query planner memilih rencana kueri yang lebih sesuai untuk kueri Anda.

Gunakan fungsi hint()

Gunakan fungsi hint() dalam kode aplikasi Anda untuk menentukan indeks mana yang harus digunakan oleh query planner untuk kueri yang mengalami replanning. Contoh:

db.<collection>.find({a:"ABC"},{b:1,_id:0}).sort({c:1}).hint({ a:1, c:1, b:1} )
Catatan

Ketika hint ditentukan untuk suatu kueri, rencana kueri yang dipilih oleh query planner tidak berlaku. Kueri akan menggunakan indeks yang ditentukan dalam hint tersebut.

Gunakan filter indeks

Gunakan filter indeks untuk membatasi indeks mana saja yang dapat dipertimbangkan oleh query planner untuk kueri yang mengalami replanning dalam kode aplikasi Anda. Contoh:

// Setel filter indeks.
db.runCommand(
   {
      planCacheSetFilter: "<collection>",
      query: { a: "ABC" },
      projection: { b: 1, _id: 0 },
      sort: { c: 1 },
      indexes: [
         { a: 1, c: 1 , b: 1 }
      ]
   }
)
// Hapus filter indeks yang ada.
db.runCommand(
   {
      planCacheClearFilters: "<collection>"
   }
)
Catatan
  • Filter indeks mengesampingkan perilaku query planner yang diharapkan saat memilih rencana kueri.

  • Jika Anda menentukan hint dan filter indeks untuk suatu kueri, filter indeks akan mengambil prioritas atas hint. Gunakan filter indeks dengan hati-hati. Untuk informasi lebih lanjut, lihat Index Filters.

Upgrade spesifikasi instans

Sebagai langkah sementara, upgrade spesifikasi instans untuk mengurangi beban database. Untuk informasi lebih lanjut, lihat Change the configurations of an instance.

Hubungi dukungan teknis

Jika masalah tetap berlanjut setelah Anda mencoba solusi di atas, Submit a ticket untuk menghubungi dukungan teknis.

Referensi