全部产品
Search
文档中心

ApsaraDB for MongoDB:Rencana kueri dan rencana ulang kueri

更新时间:Jun 27, 2025

Topik ini menjelaskan definisi rencana kueri, kemungkinan penyebab rencana ulang kueri, serta solusi yang dapat diterapkan.

Perencana Kueri

Untuk sebuah kueri, Perencana Kueri MongoDB memilih dan menyimpan dalam cache rencana kueri paling efisien berdasarkan indeks yang tersedia. Gambar berikut mengilustrasikan cara kerja Perencana Kueri.

Evaluasi rencana kueri yang paling efisien didasarkan pada jumlah unit kerja (works) yang dilakukan oleh rencana eksekusi kueri ketika Perencana Kueri mengevaluasi rencana calon. Entri rencana kueri yang disimpan dalam cache di Perencana Kueri dapat digunakan untuk kueri dengan bentuk kueri yang sama.

Entri rencana kueri yang disimpan dalam cache di Perencana Kueri dapat berada dalam salah satu dari keadaan berikut:

  • Tidak Ada: Tidak ada entri yang tersedia di dalam cache rencana kueri.

  • Tidak Aktif: Entri ada di dalam cache rencana kueri, dan nilai works dihasilkan setelah evaluasi. Entri dapat diubah menjadi keadaan Aktif.

  • Aktif: Entri ada di dalam cache rencana kueri. Rencana kueri pemenang dapat diubah menjadi keadaan Tidak Aktif.

Cache rencana kueri sepenuhnya disimpan di memori dan tidak bertahan lama. Cache dibersihkan setiap kali database MongoDB di-restart atau jika koleksi atau indeks dihapus. Cache rencana kueri memiliki batas ukuran dan mengikuti mekanisme penggantian cache Least Recently Used (LRU). Oleh karena itu, entri yang jarang diakses akan dikeluarkan dari cache seiring waktu.

Dalam kasus tertentu, Anda dapat menjalankan perintah berikut untuk mengelola rencana kueri:

  • Bersihkan cache rencana kueri dari koleksi yang ditentukan.

    db.<collection>.getPlanCache().clear()
  • Kueri semua bentuk kueri dalam koleksi yang ditentukan.

    db.<collection>.getPlanCache().listQueryShapes()
  • Kueri rencana kueri untuk kueri yang ditentukan.

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

queryHash dan planCacheKey

MongoDB 4.2 atau lebih baru memperkenalkan queryHash untuk mendefinisikan bentuk kueri. Setiap bentuk kueri dikaitkan dengan nilai queryHash. MongoDB 4.2 atau lebih baru juga memperkenalkan planCacheKey. Berbeda dengan queryHash, planCacheKey adalah fungsi dari bentuk kueri dan indeks yang tersedia untuk bentuk tersebut. Jika indeks yang mendukung bentuk kueri dibuat atau dihapus, nilai planCacheKey mungkin berubah, tetapi nilai queryHash tetap tidak berubah.

Sebagai contoh, sebuah koleksi berisi indeks dan bentuk kueri berikut:

  • Pengindeksan

    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 hanya dapat mendukung operasi kueri 2 tetapi tidak dapat mendukung operasi kueri 1. Dengan cara ini, kedua kueri memiliki nilai planCacheKey yang berbeda. Jika indeks {x:1, a:1} dibuat, nilai planCacheKey untuk kedua operasi kueri berubah.

Rencana ulang kueri

Jika terjadi perubahan data dalam koleksi, rencana kueri yang disimpan dalam cache tidak lagi sesuai untuk koleksi tersebut. Rencana kueri harus diganti untuk memastikan sinkronisasi dengan perubahan data.

Jika Anda ingin mengeksekusi rencana kueri yang memiliki bentuk kueri yang sama dengan rencana kueri yang disimpan dalam cache, Perencana Kueri tidak menghitung rencana baru tetapi langsung menggunakan rencana kueri yang tersimpan dalam cache. Perencana Kueri terus mengevaluasi efisiensi eksekusi rencana kueri yang disimpan dalam cache. Jika Perencana Kueri menentukan bahwa rencana kueri yang disimpan dalam cache kurang efisien lebih dari 10 kali dibandingkan dengan rencana kueri lain, Perencana Kueri berhenti menggunakan rencana kueri yang tersimpan dalam cache dan mengevaluasi ulang rencana kueri. Proses ini dikenal sebagai rencana ulang kueri.

Dampak dan solusi

Anda mungkin menemui kata kunci "replanned":true dalam log kueri lambat. Kata kunci ini menunjukkan bahwa Perencana Kueri tidak dapat memberikan rencana kueri yang secara konsisten efisien untuk kondisi kueri dari bentuk kueri tertentu.

Contoh 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

  • Operasi rencana ulang kueri yang sering dapat menurunkan kinerja kueri.

  • Terlalu banyak rencana ulang kueri dapat menyebabkan persaingan untuk kunci mutex, yang mengakibatkan penggunaan CPU yang tinggi.

Solusi

  • Sementara itu, tingkatkan spesifikasi instans untuk mengurangi beban database. Untuk informasi lebih lanjut, lihat Ubah Konfigurasi Instans.

  • Kami merekomendasikan Anda membersihkan rencana kueri, lalu periksa apakah analisis kueri dapat memilih rencana kueri yang lebih cocok.

  • Gunakan fungsi hint() untuk menentukan indeks untuk kondisi kueri yang direncanakan ulang dalam kode bisnis. Contoh:

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

    Jika petunjuk digunakan untuk kueri, rencana kueri yang dipilih oleh Perencana Kueri tidak berlaku.

  • Gunakan penyaringan indeks untuk membatasi indeks yang ingin Anda gunakan untuk kondisi kueri yang direncanakan ulang dalam kode bisnis. Contoh:

    // Konfigurasikan penyaringan indeks.
    db.runCommand(
       {
          planCacheSetFilter: "<collection>",
          query: { a: "ABC" },
          projection: { b: 1, _id: 0 },
          sort: { c: 1 },
          indexes: [
             { a: 1, c: 1 , b: 1 }
          ]
       }
    )
    // Hapus konfigurasi yang ada.
    db.runCommand(
       {
          planCacheClearFilters: "<collection>"
       }
    )
    Catatan
    • Penyaring indeks menggantikan perilaku yang diharapkan dari Perencana Kueri dalam memilih rencana kueri.

    • Jika Anda menentukan petunjuk dan penyaring indeks untuk kueri, penyaring indeks akan menimpa petunjuk yang ditentukan. Oleh karena itu, gunakan penyaring indeks dengan hati-hati. Untuk informasi lebih lanjut, lihat Penyaring Indeks.

  • (Direkomendasikan) Optimalkan kueri dan buat indeks yang efektif untuk kueri untuk mencegah rencana ulang kueri.

    Catatan

    Kami merekomendasikan Anda memeriksa dan memodifikasi pernyataan kueri, indeks yang tersedia, dan pola dokumen alih-alih menggunakan petunjuk dan penyaring indeks.

  • (Direkomendasikan) Jika versi utama instans Anda adalah MongoDB 4.2 atau MongoDB 4.4, kami merekomendasikan Anda memperbarui versi minor instans ke versi minor terbaru. Ini dapat secara signifikan mengurangi penggunaan kunci mutex. Anda juga dapat meningkatkan versi utama instans ke 5.0 atau 6.0 untuk menyelesaikan masalah di atas. Untuk informasi lebih lanjut tentang tiket kernel JIRA terkait, lihat SERVER-40805. Untuk informasi lebih lanjut tentang cara memperbarui versi minor instans dan meningkatkan versi utama instans, lihat Perbarui Versi Minor Instans dan Tingkatkan Versi Utama Instans.

Jika masalah tetap ada setelah Anda menggunakan metode di atas, Anda dapat

submit a ticket untuk menghubungi dukungan teknis.

Referensi