Mengoptimalkan performa kueri

Untuk memecahkan masalah kueri yang lambat, gunakan Query Explain untuk mendapatkan rencana eksekusi kueri dan profil eksekusi runtime. Bagian berikut menjelaskan langkah-langkah yang dapat Anda lakukan untuk mengoptimalkan performa kueri, bergantung pada profil eksekusinya:

Membatasi jumlah hasil

Gunakan kolom kumpulan data yang ditampilkan di hierarki eksekusi untuk mengidentifikasi apakah kueri menampilkan banyak dokumen. Pertimbangkan untuk membatasi jumlah dokumen yang ditampilkan dengan menggunakan tahap limit(...). Klausa ini mengurangi ukuran byte hasil yang diserialisasi saat ditampilkan ke klien melalui jaringan. Jika node Limit didahului oleh node MajorSort, mesin kueri dapat menggabungkan node Limit dan MajorSort serta mengganti materialisasi dan pengurutan dalam memori secara keseluruhan dengan pengurutan TopN, sehingga mengurangi persyaratan memori untuk kueri.

Membatasi Ukuran Dokumen Hasil

Pertimbangkan untuk membatasi ukuran dokumen yang ditampilkan dengan menggunakan select(...) untuk menampilkan kolom yang diperlukan saja atau remove_fields(...) untuk menghapus kolom yang terlalu besar. Klausa ini membantu mengurangi biaya komputasi dan memori untuk memproses hasil sementara dan ukuran byte hasil yang diserialisasi saat ditampilkan ke klien melalui jaringan. Jika semua kolom yang dirujuk dalam kueri tercakup oleh indeks reguler, hal ini juga memungkinkan kueri sepenuhnya tercakup oleh pemindaian indeks sehingga tidak perlu mengambil dokumen dari penyimpanan utama.

Menggunakan indeks

Gunakan petunjuk berikut untuk menyiapkan dan mengoptimalkan indeks.

Mengidentifikasi apakah kueri menggunakan indeks

Anda dapat mengidentifikasi apakah kueri menggunakan indeks dengan memeriksa node leaf di hierarki eksekusi. Jika node leaf hierarki eksekusi adalah node TableScan, artinya kueri tidak menggunakan indeks dan memindai dokumen dari penyimpanan utama. Jika indeks sedang digunakan, node leaf hierarki eksekusi akan menampilkan ID indeks dan kolom indeks dari indeks.

Mengidentifikasi indeks yang lebih baik

Indeks berguna untuk kueri jika dapat mengurangi jumlah dokumen yang perlu diambil oleh mesin kueri dari penyimpanan utama atau jika pengurutan kolomnya dapat memenuhi persyaratan Pengurutan kueri.

Jika indeks digunakan untuk kueri, tetapi mesin kueri masih mengambil dan menghapus banyak dokumen, seperti yang diidentifikasi oleh node Pemindaian yang menampilkan banyak kumpulan data dan diikuti dengan node Filter yang menampilkan sedikit kumpulan data, hal ini menandakan bahwa predikat kueri yang dipenuhi menggunakan indeks tidak selektif. Untuk membuat indeks yang lebih sesuai, lihat Membuat indeks.

Jika indeks digunakan untuk kueri, tetapi mesin kueri masih mengurutkan ulang set hasil dalam memori, seperti yang diidentifikasi oleh node MajorSort di hierarki eksekusi kueri, hal ini menandakan bahwa indeks yang digunakan tidak dapat digunakan untuk memenuhi persyaratan Pengurutan kueri. Untuk membuat indeks yang lebih sesuai, lihat bagian selanjutnya.

Membuat Indeks

Ikuti dokumentasi pengelolaan indeks untuk membuat indeks. Untuk memastikan kueri Anda dapat menggunakan indeks, buat indeks reguler (bukan Multikey) dengan kolom dalam urutan berikut:

  1. Semua kolom yang akan digunakan dalam operator kesetaraan. Untuk memaksimalkan peluang penggunaan ulang di seluruh kueri, urutkan kolom dalam urutan menurun dari kemunculan kolom dalam operator kesetaraan di antara kueri.
  2. Semua kolom yang akan diurutkan (dalam urutan yang sama).
  3. Kolom yang akan digunakan dalam operator rentang atau ketidaksetaraan dalam urutan menurun dari selektivitas batasan kueri.
  4. Kolom yang akan ditampilkan sebagai bagian dari kueri dalam indeks: menyertakan kolom tersebut dalam indeks memungkinkan indeks mencakup kueri dan tidak perlu mengambil dokumen dari penyimpanan utama.

Memaksa pemindaian indeks atau tabel

Saat Anda mengirimkan kueri Firestore dalam Mode Native, Firestore akan otomatis menggunakan indeks apa pun yang kemungkinan akan membuat kueri lebih efisien. Oleh karena itu, Anda tidak perlu menentukan indeks untuk kueri Anda. Namun, untuk kueri yang penting bagi workload Anda, sebaiknya gunakan opsi forceIndex untuk performa yang lebih konsisten.

Dalam beberapa kasus, Firestore dalam Mode Native mungkin memilih indeks yang menyebabkan latensi kueri meningkat. Jika Anda telah mengikuti langkah-langkah pemecahan masalah untuk regresi performa dan mengonfirmasi bahwa sebaiknya mencoba indeks yang berbeda untuk kueri, Anda dapat menentukan indeks menggunakan opsi forceIndex.

Anda dapat menggunakan opsi forceIndex pada tahap input apa pun dalam operasi Pipeline untuk mengganti rencana kueri default Firestore dalam Mode Native dan menentukan indeks yang akan digunakan, atau untuk memaksa pemindaian tabel.

Memaksa indeks tertentu

Untuk memaksa kueri menggunakan indeks tertentu, berikan ID indeks sebagai string ke opsi forceIndex. Anda dapat menemukan ID indeks dari konsol atau dari pesan error.

Contoh berikut memaksa perencana untuk menggunakan indeks dengan ID CICAgOi36pgK:

// Force Planner to use Index ID CICAgOi36pgK
db.pipeline()
  .collectionGroup({ collectionId: "customers", forceIndex: "CICAgOi36pgK" })
  .limit(100)

Berikut adalah beberapa kasus penggunaan untuk memaksakan indeks tertentu:

  • Menguji performa indeks yang berbeda.
  • Memastikan indeks spesifik yang diketahui optimal digunakan untuk kueri.
  • Mengganti pengoptimal saat pilihan defaultnya tidak optimal untuk kueri tertentu.

Jika indeks yang ditentukan tidak ditemukan, kueri akan gagal.

Memaksa pemindaian tabel

Pemindaian tabel membaca dokumen dalam koleksi atau grup koleksi tanpa menggunakan indeks sekunder. Untuk memaksakan pemindaian tabel, tetapkan forceIndex ke primary.

Contoh berikut memaksa pemindaian tabel:

// Force Planner to only do a Full-Table Scan
db.pipeline()
  .collectionGroup({ collectionId: "customers", forceIndex: "primary" })
  .limit(100)

Anda dapat menggunakan pemindaian tabel dalam kasus berikut:

  • Untuk koleksi yang sangat kecil yang tidak memerlukan overhead indeks.
  • Untuk kueri yang mengakses sebagian besar dokumen dalam koleksi.
  • Untuk proses debug dan perbandingan performa.

Menggunakan forceIndex dengan Query Explain

Anda dapat menggunakan Query Explain, terutama dengan opsi analyze, untuk mengamati efek forceIndex:

  • Pastikan bahwa Firestore dalam Mode Native menggunakan indeks yang ditentukan di forceIndex dengan memeriksa node leaf hierarki eksekusi untuk ID indeks.
  • Pastikan node TableScan muncul dalam rencana saat menggunakan forceIndex: "primary".
  • Bandingkan metrik performa—seperti latensi, dokumen yang dipindai, dan entri indeks yang dipindai—dengan dan tanpa forceIndex untuk menyempurnakan performa kueri.

Praktik terbaik untuk forceIndex

Meskipun forceIndex memberikan kontrol yang lebih besar atas eksekusi kueri, pengoptimal kueri Firestore dalam Mode Native umumnya efisien untuk sebagian besar kasus penggunaan. Pertimbangkan praktik terbaik berikut saat menggunakan forceIndex:

  • Gunakan forceIndex dengan bijak. Jika Anda mengamati performa yang tidak optimal dengan paket kueri default, gunakan Query Explain untuk mendiagnosis masalah sebelum memaksakan indeks.
  • Saat menggunakan forceIndex, pastikan untuk menguji kueri Anda dengan volume data yang realistis untuk memahami karakteristik performa dan biayanya.
  • Hindari penggunaan forceIndex: "primary" pada koleksi besar di lingkungan produksi.