All Products
Search
Document Center

ApsaraDB for MongoDB:Rencana kueri dan replanning kueri

Last Updated:Jul 18, 2026

Pelajari cara kerja rencana kueri MongoDB, mengapa replanning terjadi, dan cara menanganinya.

Query planner

Pengoptimal kueri MongoDB memilih dan menyimpan cache rencana kueri paling efisien untuk setiap kueri berdasarkan indeks yang tersedia.

Pengoptimal kueri mengevaluasi rencana kandidat berdasarkan jumlah unit kerja (works) yang dibutuhkan masing-masing, lalu menyimpan cache rencana pemenang. Entri cache tersebut digunakan kembali untuk kueri dengan bentuk kueri yang sama.

Entri cache rencana memiliki tiga status:

  • Missing: Tidak ada rencana dalam cache.

  • Inactive: Rencana ada dalam cache dengan nilai works yang telah dievaluasi dan dapat dipromosikan menjadi active.

  • Active: Rencana pemenang dalam cache. Dapat diturunkan statusnya menjadi inactive.

Cache rencana disimpan di memori dan tidak dipersist ke disk. Cache ini dihapus saat instans MongoDB direstart atau saat koleksi atau indeks di-drop. Cache memiliki batas ukuran dan menggunakan mekanisme eviksi LRU.

Gunakan perintah berikut untuk mengelola rencana kueri:

  • Bersihkan cache rencana untuk suatu koleksi.

    db.<collection>.getPlanCache().clear()
  • Tampilkan semua bentuk kueri untuk suatu koleksi.

    db.<collection>.getPlanCache().list()
    Catatan

    PlanCache.listQueryShapes() sudah tidak digunakan lagi sejak MongoDB 4.2. Gunakan PlanCache.list() sebagai gantinya.

  • Lihat rencana yang di-cache untuk suatu bentuk kueri.

    db.<collection>.getPlanCache().list([{ $match: { "createdFromQuery.query": { "name": "testname" }, "createdFromQuery.sort": { "name": 1 } } }])
    Catatan

    PlanCache.getPlansByQuery() sudah tidak digunakan lagi sejak MongoDB 4.2. Gunakan PlanCache.list() dengan tahap $match untuk memfilter berdasarkan bentuk kueri.

QueryHash dan planCacheKey

Mulai MongoDB 4.2, setiap bentuk kueri mendapatkan queryHash unik. planCacheKey bergantung pada bentuk kueri dan indeks yang tersedia. Menambahkan atau menghapus indeks yang mendukung bentuk kueri akan mengubah planCacheKey tetapi tidak mengubah queryHash.

Contoh 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 mendukung kueri 2 tetapi tidak mendukung kueri 1, sehingga kedua kueri tersebut memiliki kunci cache rencana yang berbeda. Menambahkan indeks {x:1, a:1} memperbarui kedua kunci cache tersebut.

Query replanning

Saat data koleksi berubah, rencana kueri yang di-cache dapat menjadi suboptimal dan perlu menyesuaikan diri.

Ketika suatu kueri sesuai dengan rencana yang di-cache, pengoptimal langsung menggunakan kembali rencana tersebut sambil memantau performanya. Jika rencana yang di-cache menjadi jauh lebih tidak efisien (misalnya, lebih dari 10 kali lebih lambat) dibandingkan alternatif lain, pengoptimal akan menghentikan eksekusi, menghapus rencana tersebut dari cache, dan mengevaluasi ulang semua kandidat. Proses ini disebut query replanning.

Dampak dan solusi

Kata kunci "replanned":true dalam log kueri lambat menunjukkan bahwa pengoptimal tidak dapat menemukan rencana yang konsisten efektif 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"

Dampak

  • Menurunkan performa kueri.

  • Menyebabkan contention mutex lock dan tingginya pemanfaatan CPU.

Solusi

  • Sementara waktu tingkatkan spesifikasi instans untuk mengurangi beban database.

  • Bersihkan cache rencana dan periksa apakah pengoptimal memilih rencana yang lebih baik.

  • Gunakan hint() dalam aplikasi Anda untuk menentukan indeks bagi kondisi kueri yang menyebabkan replanning:

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

    Petunjuk (hint) mengesampingkan perilaku default pengoptimal kueri.

  • Gunakan filter indeks untuk membatasi indeks pada kueri yang memicu replanning:

    // Periksa apakah indeks ada
    db.<collection>.getIndexes()
    
    // Tetapkan 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 sebelumnya
    db.runCommand(
       {
          planCacheClearFilters: "<collection>"
       }
    )
    Catatan
    • Filter indeks mengesampingkan perilaku default pengoptimal kueri.

    • Jika suatu kueri memiliki petunjuk (hint) dan filter indeks sekaligus, filter indeks memiliki prioritas lebih tinggi. Gunakan filter indeks dengan hati-hati. Index Filters.

    • Pengoptimal kueri menggunakan pemindaian koleksi (COLLSCAN) atau indeks yang ditentukan dalam planCacheSetFilter. Jika indeks yang ditentukan tidak ada atau disembunyikan, pengoptimal akan kembali menggunakan pemindaian koleksi, yang dapat menyebabkan penggunaan CPU dan lonjakan I/O yang tinggi. Sebelum menjalankan planCacheSetFilter, gunakan db.<collection>.getIndexes() untuk memverifikasi keberadaan indeks tersebut. planCacheSetFilter.

  • (Direkomendasikan) Optimalkan kueri dan indeks Anda untuk mencegah replanning.

    Catatan

    Petunjuk (hint) dan filter indeks merupakan solusi sementara. Meninjau kueri, indeks, dan skema dokumen Anda biasanya memberikan hasil yang lebih baik.

  • (Direkomendasikan) Untuk instans yang menjalankan versi utama 4.2 atau 4.4, perbarui ke versi minor kernel terbaru untuk mengurangi contention mutex lock (SERVER-40805), atau upgrade ke versi utama 5.0 atau 6.0. Upgrade versi minor database. Upgrade versi utama database.

Jika solusi-solusi di atas tidak menyelesaikan masalah, Anda dapat membuat tiket untuk mendapatkan dukungan teknis.

Dokumentasi terkait