Halaman ini menjelaskan konsep yang perlu dipertimbangkan saat memilih indeks Firestore dalam mode Datastore untuk aplikasi Anda.
Firestore dalam mode Datastore memberikan performa kueri yang tinggi dengan menggunakan indeks untuk semua kueri. Performa untuk sebagian besar kueri bergantung pada ukuran kumpulan hasil, dan bukan pada total ukuran database.
Firestore dalam mode Datastore menentukan indeks bawaan untuk setiap properti dalam entity. Indeks properti tunggal ini mendukung banyak kueri sederhana. Firestore dalam mode Datastore mendukung fitur penggabungan indeks yang memungkinkan database Anda menggabungkan indeks bawaan untuk mendukung kueri tambahan. Untuk kueri yang lebih kompleks, Anda harus menentukan indeks komposit terlebih dahulu.
Halaman ini berfokus pada fitur penggabungan indeks, karena fitur ini memengaruhi dua peluang pengoptimalan indeks yang penting:
- Mempercepat kueri
- Mengurangi jumlah indeks komposit
Contoh berikut menunjukkan fitur penggabungan indeks.
Memfilter entity Photo
Pertimbangkan database mode Datastore
dengan entity jenis Photo
:
Foto | ||
---|---|---|
Properti | Jenis nilai | Deskripsi |
owner_id |
String | ID pengguna |
tag |
Array string | Kata kunci dengan token |
size |
Bilangan bulat |
Enumerasi:
|
coloration |
Bilangan bulat |
Enumerasi:
|
Bayangkan Anda memerlukan fitur aplikasi yang memungkinkan pengguna membuat kueri entity Photo
berdasarkan AND
logis dari hal berikut:
Maksimal tiga filter berdasarkan properti:
owner_id
size
coloration
String penelusuran
tag
. Aplikasi ini membuat token string penelusuran menjadi tag dan menambahkan filter untuk setiap tag.Misalnya, aplikasi mengubah string penelusuran
outside, family
menjadi filter kueritag=outside
dantag=family
.
Dengan menggunakan indeks bawaan dan fitur penggabungan indeks Firestore dalam mode Datastore, Anda dapat memenuhi persyaratan indeks fitur filter Photo
ini tanpa menambahkan indeks komposit tambahan.
Indeks bawaan untuk entity Photo
mendukung kueri filter tunggal
seperti:
Python
Fitur filter Photo
juga memerlukan kueri yang menggabungkan beberapa filter kesetaraan dengan AND
yang logis:
Python
Firestore dalam mode Datastore dapat mendukung kueri ini dengan menggabungkan indeks bawaan.
Penggabungan indeks
Firestore dalam mode Datastore dapat menggunakan penggabungan indeks saat kueri dan indeks Anda memenuhi semua batasan berikut:
- Kueri hanya menggunakan filter kesetaraan (
=
) - Tidak ada indeks gabungan yang cocok dengan filter dan urutan kueri
- Setiap filter persamaan cocok dengan setidaknya satu indeks yang ada dengan pengurutan yang sama seperti kueri
Dalam situasi ini, Firestore dalam mode Datastore dapat menggunakan indeks yang ada untuk mendukung kueri, bukan mengharuskan Anda mengonfigurasi indeks komposit tambahan.
Jika dua atau beberapa indeks diurutkan berdasarkan kriteria yang sama, Firestore dalam mode Datastore dapat menggabungkan hasil dari beberapa pemindaian indeks untuk menemukan hasil yang sama untuk semua indeks tersebut. Firestore dalam mode Datastore dapat menggabungkan indeks bawaan, karena semua indeks tersebut mengurutkan nilai menurut kunci entity.
Dengan menggabungkan indeks bawaan, Firestore dalam mode Datastore mendukung kueri dengan filter kesetaraan di beberapa properti:
Python
Firestore dalam mode Datastore juga dapat menggabungkan hasil indeks dari beberapa bagian indeks yang sama. Dengan menggabungkan berbagai bagian indeks bawaan untuk properti tag
, Firestore dalam mode Datastore mendukung kueri yang menggabungkan beberapa filter tag
dalam AND
yang logis:
Python
Kueri yang didukung oleh indeks bawaan yang digabungkan melengkapi kumpulan kueri
yang diperlukan oleh fitur pemfilteran Photo
. Perhatikan bahwa mendukung fitur pemfilteran Photo
tidak memerlukan indeks komposit tambahan.
Saat memilih indeks yang optimal untuk aplikasi Anda, penting untuk memahami fitur penggabungan indeks. Penggabungan indeks memberi Firestore dalam mode Datastore fleksibilitas kueri yang lebih besar, tetapi dengan kemungkinan kompromi pada performa. Bagian berikut menjelaskan performa penggabungan indeks, dan cara meningkatkan performa dengan menambahkan indeks komposit.
Menemukan indeks yang sempurna
Indeks diurutkan terlebih dahulu berdasarkan ancestor, lalu berdasarkan nilai properti, dalam urutan yang ditentukan dalam definisi indeks. Indeks gabungan sempurna untuk kueri, yang memungkinkan kueri dijalankan dengan paling efisien, ditentukan pada properti berikut, secara berurutan:
- Properti yang digunakan dalam filter kesetaraan
- Properti yang digunakan dalam tata urutan
- Properti yang digunakan dalam filter
distinctOn
- Properti yang digunakan dalam filter rentang & ketidaksetaraan (yang belum disertakan dalam tata urutan)
- Properti yang digunakan dalam agregasi dan proyeksi (yang belum disertakan dalam tata urutan serta filter rentang & ketidaksetaraan)
Hal ini memastikan bahwa semua hasil untuk setiap kemungkinan eksekusi kueri diperhitungkan. Database Firestore dalam mode Datastore menjalankan kueri menggunakan indeks sempurna menggunakan langkah-langkah berikut:
- Mengidentifikasi indeks yang sesuai dengan jenis, properti filter, operator filter, dan tata urutan pada kueri
- Memindai dari awal indeks hingga entity pertama yang memenuhi semua atau sebagian kondisi filter kueri
- Terus memindai indeks, menampilkan setiap entity yang memenuhi semua kondisi filter, hingga
- menemukan entity yang tidak memenuhi kondisi filter, atau
- mencapai akhir indeks, atau
- telah mengumpulkan jumlah hasil maksimum yang diminta oleh kueri
Misalnya, pertimbangkan kueri berikut:
SELECT * FROM Task
WHERE category = 'Personal'
AND priority < 3
ORDER BY priority DESC
Indeks komposit yang sempurna untuk kueri ini adalah indeks kunci untuk entity jenis Task
, dengan kolom untuk nilai properti category
dan priority
. Indeks diurutkan terlebih dahulu dalam urutan menaik berdasarkan category
, lalu dalam urutan menurun berdasarkan priority
:
indexes:
- kind: Task
properties:
- name: category
direction: asc
- name: priority
direction: desc
Dua kueri dengan bentuk yang sama tetapi dengan nilai filter yang berbeda menggunakan indeks yang sama. Misalnya, kueri berikut menggunakan indeks yang sama dengan kueri sebelumnya:
SELECT * FROM Task
WHERE category = 'Work'
AND priority < 5
ORDER BY priority DESC
Untuk indeks ini
indexes:
- kind: Task
properties:
- name: category
direction: asc
- name: priority
direction: asc
- name: created
direction: asc
Indeks sebelumnya dapat memenuhi kedua kueri berikut:
SELECT * FROM Task
WHERE category = 'Personal'
AND priority = 5
ORDER BY created ASC
dan
SELECT * FROM Task
WHERE category = 'Work'
ORDER BY priority ASC, created ASC
Mengoptimalkan pilihan indeks
Bagian ini menjelaskan karakteristik performa penggabungan indeks dan dua peluang pengoptimalan yang terkait dengan penggabungan indeks:
- Menambahkan indeks komposit untuk mempercepat kueri yang mengandalkan indeks gabungan
- Mengurangi jumlah indeks komposit dengan memanfaatkan indeks gabungan
Performa penggabungan indeks
Dalam penggabungan indeks, Firestore dalam mode Datastore menggabungkan indeks secara efisien menggunakan algoritma join penggabungan zig-zag. Dengan menggunakan algoritma ini, mode Datastore menggabungkan potensi kecocokan dari beberapa pemindaian indeks untuk menghasilkan set hasil yang cocok dengan kueri. Penggabungan indeks menggabungkan komponen filter pada waktu baca, bukan waktu tulis. Tidak seperti kebanyakan kueri Firestore dalam mode Datastore yang performanya hanya bergantung pada ukuran kumpulan hasil, performa untuk kueri penggabungan indeks bergantung pada filter dalam kueri dan jumlah potensi kecocokan yang dipertimbangkan database.
Performa terbaik penggabungan indeks terjadi saat setiap potensi kecocokan
dalam indeks memenuhi filter kueri. Dalam hal ini, performa adalah O(R * I)
dengan R
adalah ukuran kumpulan hasil dan I
adalah jumlah indeks yang dipindai.
Performa terburuk terjadi saat database harus mempertimbangkan banyak potensi pencocokan, tetapi hanya sedikit yang memenuhi filter kueri. Dalam hal ini,
performa adalah O(S)
dengan S
adalah ukuran kumpulan
entitas potensial terkecil dari satu pemindaian indeks.
Performa sebenarnya bergantung pada bentuk data. Jumlah
rata-rata entity yang dipertimbangkan untuk setiap hasil yang ditampilkan adalah
O(S/(R * I))
. Performa kueri akan lebih buruk jika banyak entity cocok dengan setiap pemindaian indeks, tetapi hanya sedikit entity yang cocok dengan kueri secara keseluruhan, yang berarti R
kecil dan S
besar.
Ada empat hal yang dapat memitigasi risiko ini:
Perencana kueri tidak akan mencari entitas hingga mengetahui bahwa entitas cocok dengan seluruh kueri.
Algoritma zig-zag tidak perlu menemukan semua hasil untuk menampilkan hasil berikutnya. Jika meminta 10 hasil pertama, Anda hanya membayar latensi untuk menemukan 10 hasil tersebut.
Algoritme zig-zag melewati sebagian besar hasil positif palsu. Performa terburuk hanya terjadi jika hasil positif palsu terjalin dengan sempurna (dalam urutan pengurutan) di antara pemindaian.
Latensi bergantung pada jumlah entity yang ditemukan di setiap pemindaian indeks, bukan jumlah entity yang cocok dengan setiap filter. Seperti yang ditunjukkan di bagian berikutnya, Anda dapat menambahkan indeks komposit untuk meningkatkan performa penggabungan indeks.
Mempercepat kueri penggabungan indeks
Saat Firestore dalam mode Datastore menggabungkan indeks, setiap pemindaian indeks sering dipetakan ke satu filter dalam kueri. Anda dapat meningkatkan performa kueri dengan menambahkan indeks gabungan yang cocok dengan beberapa filter dalam kueri.
Pertimbangkan kueri ini:
Python
Setiap filter dipetakan ke satu pemindaian indeks dalam indeks bawaan berikut:
Index(Photo, owner_id) Index(Photo, size) Index(Photo, tag)
Jika Anda menambahkan indeks gabungan Index(Photo, owner_id, size)
, kueri akan dipetakan ke dua pemindaian indeks, bukan tiga:
# Satisfies both 'owner_id=username' and 'size=2'
Index(Photo, owner_id, size)
Index(Photo, tag)
Pertimbangkan skenario dengan banyak gambar besar, banyak gambar hitam-putih, tetapi sedikit gambar panorama besar. Pemfilteran kueri untuk gambar panorama dan hitam putih akan lambat jika menggabungkan indeks bawaan:
Python
Untuk meningkatkan performa kueri, Anda dapat menurunkan nilai S
(kumpulan entity
terkecil dalam satu pemindaian indeks) di O(S/(R * I))
dengan
menambahkan indeks gabungan berikut:
Index(Photo, size, coloration)
Dibandingkan dengan menggunakan dua indeks bawaan, indeks komposit ini menghasilkan lebih sedikit potensi hasil untuk dua filter kueri yang sama. Pendekatan ini secara substansial meningkatkan performa dengan mengorbankan satu indeks lagi.
Mengurangi jumlah indeks komposit dengan penggabungan indeks
Meskipun indeks komposit yang sama persis dengan filter dalam kueri berperforma terbaik, menambahkan indeks komposit untuk setiap kombinasi filter tidak selalu merupakan hal terbaik atau mungkin. Anda harus menyeimbangkan indeks komposit dengan hal berikut:
Batas indeks komposit:
Batas Jumlah Jumlah maksimum indeks komposit untuk database -
200 jika Anda belum mengaktifkan penagihan untuk project Google Cloud Anda.
Jika memerlukan kuota lebih banyak, Anda harus mengaktifkan penagihan untuk project Google Cloud Anda.
-
500 jika Anda mengaktifkan penagihan untuk project Google Cloud Anda.
Anda dapat menghubungi dukungan untuk meminta peningkatan batas ini.
Jumlah maksimum ukuran entri indeks komposit entity 2 MiB Jumlah maksimum hal berikut untuk entity: - jumlah nilai properti yang diindeks
- jumlah entri indeks komposit
20.000 -
- Biaya penyimpanan setiap indeks tambahan.
- Pengaruh pada latensi tulis.
Masalah pengindeksan sering kali muncul dengan kolom multi-nilai seperti properti tag
dari entity Photo
.
Misalnya, bayangkan bahwa fitur pemfilteran Photo
kini perlu mendukung
klausa pengurutan menurun berdasarkan empat properti tambahan:
Foto | ||
---|---|---|
Properti | Jenis nilai | Deskripsi |
date_added |
Bilangan bulat | Tanggal/waktu |
rating |
Float | Rating pengguna gabungan |
comment_count |
Bilangan bulat | Jumlah komentar |
download_count |
Bilangan bulat | Jumlah download |
Jika Anda mengabaikan kolom tag
, Anda dapat memilih
indeks gabungan yang cocok dengan setiap kombinasi filter Photo
:
Index(Photo, owner_id, -date_added) Index(Photo, owner_id, -comments) Index(Photo, size, -date_added) Index(Photo, size, -comments) ... Index(Photo, owner_id, size, -date_added) Index(Photo, owner_id, size, -comments) ... Index(Photo, owner_id, size, coloration, -date_added) Index(Photo, owner_id, size, coloration, -comments)
Jumlah total indeks komposit adalah:
2^(number of filters) * (number of different orders) = 2 ^ 3 * 4 = 32 composite indexes
Jika Anda mencoba mendukung hingga 3 filter tag
, jumlah total indeks
komposit adalah:
2 ^ (3 + 3 tag filters) * 4 = 256 indexes.
Indeks yang menyertakan properti multi-nilai seperti
tag
juga menyebabkan
masalah indeks meledak yang
meningkatkan biaya penyimpanan dan latensi tulis.
Untuk mendukung filter di kolom tag
untuk fitur ini, Anda dapat mengurangi jumlah
total indeks dengan mengandalkan indeks gabungan. Kumpulan indeks komposit berikut adalah minimum yang diperlukan untuk mendukung fitur pemfilteran Photo
dengan pengurutan:
Index(Photo, owner_id, -date_added) Index(Photo, owner_id, -rating) Index(Photo, owner_id, -comments) Index(Photo, owner_id, -downloads) Index(Photo, size, -date_added) Index(Photo, size, -rating) Index(Photo, size, -comments) Index(Photo, size, -downloads) ... Index(Photo, tag, -date_added) Index(Photo, tag, -rating) Index(Photo, tag, -comments) Index(Photo, tag, -downloads)
Jumlah indeks komposit yang ditentukan adalah:
(number of filters + 1) * (number of orders) = 7 * 4 = 28
Penggabungan indeks juga memberikan manfaat berikut:
- Memungkinkan entity
Photo
mendukung hingga 1.000 tag tanpa batas jumlah filtertag
per kueri. - Mengurangi jumlah total indeks yang mengurangi biaya penyimpanan dan latensi tulis.
Memilih indeks untuk aplikasi
Anda dapat memilih indeks yang optimal untuk database mode Datastore menggunakan dua pendekatan:
Menggunakan penggabungan indeks untuk mendukung kueri tambahan
- Memerlukan lebih sedikit indeks komposit
- Mengurangi biaya penyimpanan per entitas
- Meningkatkan latensi tulis
- Menghindari indeks yang meledak
- Performa bergantung pada bentuk data
Menentukan indeks gabungan yang cocok dengan beberapa filter dalam kueri
- Meningkatkan performa kueri
- Performa kueri yang konsisten dan tidak bergantung pada bentuk data
- Tidak boleh melebihi batas indeks komposit
- Peningkatan biaya penyimpanan per entitas
- Peningkatan latensi tulis
Saat mencari tahu indeks yang optimal untuk aplikasi Anda, jawabannya dapat berubah seiring perubahan bentuk data Anda. Mengambil sampel performa kueri memberi Anda gambaran yang baik tentang kueri umum aplikasi dan kueri yang lambat. Dengan informasi ini, Anda dapat menambahkan indeks untuk meningkatkan performa kueri yang umum dan lambat.