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:
- 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.
- Semua kolom yang akan diurutkan (dalam urutan yang sama).
- Kolom yang akan digunakan dalam operator rentang atau ketidaksetaraan dalam urutan menurun dari selektivitas batasan kueri.
- 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
forceIndexdengan memeriksa node leaf hierarki eksekusi untuk ID indeks. - Pastikan node
TableScanmuncul dalam rencana saat menggunakanforceIndex: "primary". - Bandingkan metrik performa—seperti latensi, dokumen yang dipindai, dan entri
indeks yang dipindai—dengan dan tanpa
forceIndexuntuk 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
forceIndexdengan 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.