Praktik terbaik

Gunakan praktik terbaik yang tercantum di sini sebagai referensi cepat saat membangun aplikasi yang menggunakan Firestore.

Lokasi database

Saat Anda membuat instance database, pilih lokasi database yang terdekat dengan pengguna dan resource komputasi. Hop jaringan dengan jangkauan jauh lebih rentan terhadap error dan meningkatkan latensi kueri.

Untuk memaksimalkan ketersediaan dan ketahanan aplikasi Anda, pilih lokasi multi-region dan tempatkan resource komputasi kritis di minimal dua region.

Pilih lokasi regional untuk biaya yang lebih rendah, untuk latensi tulis yang lebih rendah jika aplikasi Anda sensitif terhadap latensi, atau untuk berbagi lokasi dengan resource GCP lainnya.

ID dokumen

  • Hindari ID dokumen . dan ...
  • Hindari penggunaan garis miring / di ID dokumen.
  • Jangan gunakan ID dokumen yang meningkat secara monoton, seperti:

    • Customer1, Customer2, Customer3, ...
    • Product 1, Product 2, Product 3, ...

    ID berurutan tersebut dapat menyebabkan hotspot yang memengaruhi latensi.

Nama Kolom

  • Hindari penggunaan karakter berikut dalam nama kolom karena memerlukan escaping tambahan:

    • . titik
    • [ kurung siku kiri
    • ] kurung siku kanan
    • * tanda bintang
    • ` kutip tunggal terbalik

Indeks

Mengurangi latensi tulis

Kontributor utama untuk latensi tulis adalah fanout indeks. Praktik terbaik untuk mengurangi fanout indeks adalah:

  • Tetapkan pengecualian indeks tingkat koleksi. Default yang mudah adalah menonaktifkan pengindeksan Menurun & Array. Menghapus nilai terindeks yang tidak digunakan juga akan menurunkan biaya penyimpanan.

  • Mengurangi jumlah dokumen dalam transaksi. Untuk menulis dokumen dalam jumlah besar, pertimbangkan untuk menggunakan penulis massal, bukan penulis batch atomik.

Pengecualian indeks

Untuk sebagian besar aplikasi, Anda dapat mengandalkan pengindeksan otomatis serta link pesan error apa pun untuk mengelola indeks Anda. Namun, Anda mungkin ingin menambahkan pengecualian kolom tunggal dalam kasus berikut:

Kasus Deskripsi
Kolom string berukuran lebar

Jika memiliki kolom string yang biasanya memuat nilai string panjang yang tidak digunakan untuk membuat kueri, Anda dapat menghemat biaya penyimpanan dengan mengecualikan kolom tersebut dari pengindeksan.

Tingkat operasi tulis yang tinggi ke koleksi yang berisi dokumen dengan nilai berurutan

Jika Anda mengindeks kolom yang meningkat atau menurun secara berurutan antardokumen dalam koleksi, misalnya stempel waktu, tingkat operasi tulis maksimum ke koleksi itu adalah 500 penulisan per detik. Jika tidak membuat kueri berdasarkan kolom yang memuat nilai berurutan, Anda dapat mengecualikan kolom itu dari pengindeksan untuk mengabaikan batas ini.

Dalam kasus penggunaan IoT dengan tingkat operasi tulis yang tinggi, koleksi yang berisi dokumen dengan kolom stempel waktu mungkin akan mendekati batas 500 operasi tulis per detik.

Kolom TTL

Jika Anda menggunakan kebijakan TTL (time-to-live), perhatikan bahwa kolom TTL harus berupa stempel waktu. Pengindeksan pada kolom TTL diaktifkan secara default dan dapat memengaruhi performa pada tingkat traffic yang lebih tinggi. Sebagai praktik terbaik, tambahkan pengecualian satu kolom untuk kolom TTL Anda.

Kolom peta atau array berukuran lebar

Kolom peta atau array berukuran lebar dapat mendekati batas entri indeks sebesar 40.000 per dokumen. Jika Anda tidak membuat kueri berdasarkan kolom peta atau array berukuran lebar, sebaiknya Anda mengecualikannya dari pengindeksan.

Operasi baca dan tulis

  • Tingkat maksimum persis yang dapat digunakan aplikasi untuk memperbarui satu dokumen sangat bergantung pada beban kerja. Untuk mengetahui informasi lebih lanjut, lihat Pembaruan pada satu dokumen.

  • Gunakan panggilan asinkron jika bisa, bukan panggilan sinkron. Panggilan asinkron meminimalkan dampak latensi. Misalnya, pertimbangkan aplikasi yang membutuhkan hasil pencarian dokumen dan hasil kueri sebelum merender respons. Jika pencarian dan kueri tidak memiliki dependensi data, maka tidak perlu menunggu secara sinkron sampai pencarian selesai sebelum memulai kueri.

  • Jangan gunakan offset. Sebagai gantinya, gunakan cursors. Penggunaan offset hanya akan menghindari menampilkan dokumen yang dilewati di aplikasi Anda, tetapi dokumen tersebut masih diambil secara internal. Dokumen yang dilewati memengaruhi latensi kueri dan aplikasi Anda akan dikenai biaya untuk operasi baca yang diperlukan untuk mengambil dokumen tersebut.

Upaya coba lagi transaksi

SDK dan library klien Firestore secara otomatis mencoba kembali transaksi yang gagal untuk menangani error sementara. Jika aplikasi Anda mengakses Firestore melalui REST atau RPC API secara langsung, bukan melalui SDK, aplikasi Anda harus menerapkan upaya coba lagi transaksi untuk meningkatkan keandalan.

Update realtime

Untuk praktik terbaik yang terkait dengan update real-time, lihat Memahami kueri real-time dalam skala besar.

Mendesain untuk penskalaan

Praktik terbaik berikut menjelaskan cara menghindari situasi yang menciptakan masalah pertentangan.

Pembaruan untuk satu dokumen

Saat mendesain aplikasi, pertimbangkan seberapa cepat aplikasi mengupdate satu dokumen. Cara terbaik untuk menggambarkan performa beban kerja Anda adalah dengan melakukan pengujian beban. Tingkat maksimum persis yang dapat digunakan aplikasi untuk memperbarui satu dokumen sangat bergantung pada beban kerja. Faktornya meliputi kecepatan tulis, pertentangan di antara permintaan, dan jumlah indeks yang terpengaruh.

Operasi tulis dokumen memperbarui dokumen beserta indeks terkait, dan Firestore secara sinkron menerapkan operasi tulis di seluruh kuorum replika. Dengan kecepatan tulis yang cukup tinggi, database akan mulai mengalami pertentangan, latensi yang lebih tinggi, atau error lainnya.

Kecepatan baca, tulis, dan hapus yang tinggi untuk rentang dokumen yang sempit

Hindari kecepatan baca atau tulis yang tinggi ke dokumen yang mirip secara leksikografis, atau aplikasi Anda akan mengalami error pertentangan. Masalah ini dikenal sebagai hotspotting dan aplikasi Anda dapat mengalami hotspotting jika melakukan salah satu dari hal berikut:

  • Membuat dokumen baru dengan kecepatan yang sangat tinggi dan mengalokasikan ID yang meningkat secara monoton miliknya sendiri.

    Firestore mengalokasikan ID dokumen menggunakan algoritma sebar. Anda seharusnya tidak mengalami hotspotting pada penulisan jika membuat dokumen baru menggunakan ID dokumen otomatis.

  • Membuat dokumen baru dengan kecepatan tinggi dalam koleksi dengan sedikit dokumen.

  • Membuat dokumen baru dengan kolom yang meningkat secara monoton, seperti stempel waktu, dengan kecepatan yang sangat tinggi.

  • Menghapus dokumen dalam koleksi dengan kecepatan tinggi.

  • Menulis ke database dengan kecepatan yang sangat tinggi tanpa meningkatkan traffic secara bertahap.

Menghindari melewati data yang dihapus

Hindari kueri yang melewati data yang belum lama dihapus. Kueri mungkin harus melewati sejumlah besar entri indeks jika hasil kueri awal baru dihapus.

Contoh beban kerja yang mungkin harus melewati banyak data yang telah dihapus adalah beban kerja yang mencoba menemukan item pekerjaan terlama yang ada dalam antrean. Kueri mungkin terlihat seperti ini:

docs = db.collection('WorkItems').order_by('created').limit(100)
delete_batch = db.batch()
for doc in docs.stream():
  finish_work(doc)
  delete_batch.delete(doc.reference)
delete_batch.commit()

Setiap kali dijalankan, kueri ini akan memindai entri indeks untuk mencari kolom created pada dokumen yang belum lama dihapus. Langkah ini akan memperlambat kueri.

Untuk meningkatkan performa, gunakan metode start_at guna menemukan tempat terbaik untuk memulai. Contoh:

completed_items = db.collection('CompletionStats').document('all stats').get()
docs = db.collection('WorkItems').start_at(
    {'created': completed_items.get('last_completed')}).order_by(
        'created').limit(100)
delete_batch = db.batch()
last_completed = None
for doc in docs.stream():
  finish_work(doc)
  delete_batch.delete(doc.reference)
  last_completed = doc.get('created')

if last_completed:
  delete_batch.update(completed_items.reference,
                      {'last_completed': last_completed})
  delete_batch.commit()

CATATAN: Contoh di atas menggunakan kolom yang meningkat secara monoton, yang merupakan anti-pola untuk kecepatan tulis yang tinggi.

Meningkatkan traffic

Anda harus secara bertahap meningkatkan traffic ke koleksi baru atau dokumen yang mirip secara leksikografis agar memberikan cukup waktu bagi Firestore untuk menyiapkan dokumen bagi traffic yang meningkat. Sebaiknya mulai dengan maksimum 500 operasi per detik ke koleksi baru, lalu tingkatkan traffic sebesar 50% setiap 5 menit. Anda juga dapat meningkatkan traffic operasi tulis, tetapi perhatikan Batas Standar Firestore. Pastikan bahwa operasi didistribusikan relatif merata di semua rentang kunci. Ini disebut dengan aturan "500/50/5".

Memigrasikan traffic ke koleksi baru

Kenaikan bertahap sangat penting jika Anda memigrasi traffic aplikasi dari satu koleksi ke koleksi lainnya. Cara sederhana untuk menangani migrasi ini adalah dengan membaca dari koleksi lama, namun jika dokumen tidak ada, membaca dari koleksi baru. Namun, hal ini dapat menyebabkan peningkatan traffic secara tiba-tiba ke dokumen yang mirip secara leksikografis dalam koleksi baru. Firestore mungkin tidak dapat menyiapkan koleksi baru secara efisien untuk traffic yang meningkat, terutama jika koleksi tersebut berisi sedikit dokumen.

Masalah serupa dapat terjadi jika Anda mengubah ID banyak dokumen dalam koleksi yang sama.

Strategi terbaik untuk memigrasi traffic ke koleksi baru tergantung pada model data Anda. Di bawah ini adalah contoh strategi yang disebut operasi baca paralel. Anda perlu menentukan apakah strategi ini efektif untuk data Anda atau tidak, dan pertimbangan pentingnya adalah dampak biaya operasi paralel selama migrasi.

Operasi baca paralel

Untuk menerapkan operasi baca paralel saat Anda memigrasi traffic ke koleksi baru, baca dari koleksi lama terlebih dahulu. Jika dokumen tidak ada, baca dari koleksi baru. Kecepatan baca yang tinggi untuk dokumen yang tidak ada dapat menyebabkan hotspotting. Jadi, pastikan untuk secara bertahap meningkatkan beban ke koleksi baru. Strategi yang lebih baik adalah menyalin dokumen lama ke koleksi baru, lalu menghapus dokumen lama. Tingkatkan operasi baca paralel secara bertahap untuk memastikan bahwa Firestore dapat menangani traffic ke koleksi baru.

Strategi yang memungkinkan untuk secara bertahap meningkatkan operasi baca atau tulis pada koleksi baru adalah dengan menggunakan hash deterministik ID pengguna untuk memilih persentase acak dari pengguna yang mencoba menulis dokumen baru. Pastikan bahwa hasil hash ID pengguna tidak condong ke pengguna tertentu karena fungsi Anda atau perilaku pengguna.

Sementara itu, jalankan tugas batch yang menyalin semua data Anda dari dokumen lama ke koleksi baru. Tugas batch Anda harus menghindari penulisan ke ID dokumen berurutan untuk mencegah hotspot. Ketika tugas batch selesai, Anda hanya dapat membaca dari koleksi baru.

Perbaikan strategi ini dapat berupa migrasi pengguna dalam batch kecil pada satu waktu. Tambahkan kolom ke dokumen pengguna yang melacak status migrasi pengguna tersebut. Pilih sekelompok pengguna yang akan dimigrasi berdasarkan hash ID pengguna. Gunakan tugas batch untuk memigrasi dokumen untuk sekelompok pengguna tersebut, dan gunakan operasi baca paralel untuk pengguna di tengah migrasi.

Perlu diperhatikan bahwa Anda tidak dapat melakukan roll back dengan mudah, kecuali Anda melakukan operasi tulis ganda pada entity lama dan baru selama fase migrasi. Hal ini akan meningkatkan biaya Firestore yang timbul.

Privasi

  • Hindari menyimpan informasi sensitif di Cloud Project ID. ID Project Cloud mungkin dipertahankan di luar masa berlaku project Anda.
  • Sebagai praktik terbaik kepatuhan data, sebaiknya jangan simpan informasi sensitif dalam nama dokumen dan nama kolom dokumen.