Memahami performa kueri menggunakan Query Explain

Query Explain memungkinkan Anda untuk mengirimkan kueri Cloud Firestore ke backend dan menerima statistik performa terperinci tentang eksekusi kueri backend sebagai gantinya. Fitur ini berfungsi seperti operasi EXPLAIN [ANALYZE] di banyak sistem database relasional.

Permintaan Query Explain dapat dikirim menggunakan library klien server Firestore.

Hasil Query Explain membantu memahami bagaimana kueri dijalankan, yang menunjukkan kepada Anda inefisiensi dan lokasi kemungkinan adanya bottleneck di sisi server.

Query Explain:

  • Memberikan insight tentang fase perencanaan kueri sehingga Anda dapat menyesuaikan indeks kueri dan meningkatkan efisiensi.
  • Dengan opsi analisis, Anda dapat memahami biaya dan performa yang dihitung per kueri dan memungkinkan Anda dengan cepat melakukan iterasi pola kueri yang berbeda guna mengoptimalkan penggunaannya.

Memahami opsi Query Explain: opsi default dan analisis

Operasi Query Explain dapat dijalankan menggunakan opsi default atau analisis.

Dengan opsi default, Query Explain merencanakan kueri, tetapi melewati tahap eksekusi. Opsi ini akan menampilkan informasi tahap perencana. Anda dapat menggunakannya untuk memeriksa apakah kueri memiliki indeks yang diperlukan dan memahami indeks yang digunakan. Hal ini akan membantu Anda memverifikasi, misalnya, kueri tertentu menggunakan indeks gabungan daripada harus bersinggungan dengan banyak indeks yang berbeda.

Dengan opsi analisis, Query Explain merencanakan sekaligus menjalankan kueri. Opsi ini akan menampilkan semua informasi perencana yang disebutkan sebelumnya beserta statistik dari runtime eksekusi kueri. Hal ini mencakup informasi penagihan kueri beserta insight tingkat sistem ke dalam eksekusi kueri. Anda dapat menggunakan alat ini untuk menguji berbagai konfigurasi kueri dan indeks untuk mengoptimalkan biaya dan latensi.

Berapa biaya Query Explain?

Saat Anda menggunakan Query Explain dengan opsi default, tidak ada operasi indeks atau baca yang dijalankan. Terlepas dari kompleksitas kueri, satu operasi baca akan dikenai biaya.

Saat menggunakan Query Explain dengan opsi analisis, operasi indeks dan operasi baca akan dijalankan, sehingga Anda akan dikenai biaya untuk kueri tersebut seperti biasa. Tidak ada biaya tambahan untuk aktivitas analisis, hanya biaya biasa untuk kueri yang dijalankan.

Menggunakan Query Explain dengan opsi default

Anda dapat menggunakan library klien untuk mengirimkan permintaan opsi default.

Perlu diperhatikan bahwa permintaan diautentikasi dengan IAM, menggunakan izin yang sama dengan operasi kueri reguler. Teknik autentikasi lainnya, seperti Firebase Authentication, akan diabaikan. Untuk informasi selengkapnya, lihat panduan di IAM untuk library klien server.

Java (Admin)

Query q = db.collection("col").whereGreaterThan("a", 1);
ExplainOptions options = ExplainOptions.builder().build();

ExplainResults<QuerySnapshot> explainResults = q.explain(options).get();
ExplainMetrics metrics = explainResults.getMetrics();
PlanSummary planSummary = metrics.getPlanSummary();

    
Node (Admin)

const q = db.collection('col').where('country', '=', 'USA');
const options = { analyze : 'false' };

const explainResults = await q.explain(options);

const metrics = explainResults.metrics;
const plan = metrics.planSummary;

    

Format respons yang tepat bergantung pada lingkungan eksekusi. Hasil yang ditampilkan dapat dikonversi ke JSON. Contoh:

{
    "indexes_used": [
        {"query_scope": "Collection", "properties": "(category ASC, __name__ ASC)"},
        {"query_scope": "Collection", "properties": "(country ASC, __name__ ASC)"},
    ]
}

Untuk informasi selengkapnya, lihat referensi laporan Query Explain.

Menggunakan Query Explain dengan opsi analisis

Anda dapat menggunakan library klien untuk mengirimkan permintaan opsi analisis.

Perlu diperhatikan bahwa permintaan diautentikasi dengan IAM, menggunakan izin yang sama dengan operasi kueri reguler. Teknik autentikasi lainnya, seperti Firebase Authentication, akan diabaikan. Untuk informasi selengkapnya, lihat panduan di IAM untuk library klien server.

Java (Admin)

Query q = db.collection("col").whereGreaterThan("a", 1);

ExplainOptions options = ExplainOptions.builder().setAnalyze(true).build();

ExplainResults<QuerySnapshot> explainResults = q.explain(options).get();

ExplainMetrics metrics = explainResults.getMetrics();
PlanSummary planSummary = metrics.getPlanSummary();
List<Map<String, Object>> indexesUsed = planSummary.getIndexesUsed();
ExecutionStats stats = metrics.getExecutionStats();

    
Node (Admin)

const q = db.collection('col').where('country', '=', 'USA');

const options = { analyze : 'true' };

const explainResults = await q.explain(options);

const metrics = explainResults.metrics;
const plan = metrics.planSummary;
const indexesUsed = plan.indexesUsed;
const stats = metrics.executionStats;

    

Contoh berikut menunjukkan objek stats yang ditampilkan selain planInfo. Format respons yang tepat bergantung pada lingkungan eksekusi. Contoh respons dalam format JSON.

{
    "resultsReturned": "5",
    "executionDuration": "0.100718s",
    "readOperations": "5",
    "debugStats": {
               "index_entries_scanned": "95000",
               "documents_scanned": "5"
               "billing_details": {
                     "documents_billable": "5",
                     "index_entries_billable": "0",
                     "small_ops": "0",
                     "min_query_cost": "0",
               }
    }

}

Untuk informasi selengkapnya, lihat referensi laporan Query Explain.

Menafsirkan hasil dan melakukan penyesuaian

Mari kita lihat sebuah contoh skenario di mana kita membuat kueri film berdasarkan genre dan negara produksi.

Sebagai ilustrasi, asumsikan nilai yang setara dengan kueri SQL ini.

SELECT *
FROM /movies
WHERE category = 'Romantic' AND country = 'USA';

Jika kita menggunakan opsi analisis, metrik yang ditampilkan menunjukkan kueri berjalan pada dua indeks kolom tunggal, (category ASC, __name__ ASC) dan (country ASC, __name__ ASC). Opsi ini memindai 16.500 entri indeks, tetapi hanya menampilkan 1.200 dokumen.

// Output query planning info
{
    "indexes_used": [
        {"query_scope": "Collection", "properties": "(category ASC, __name__ ASC)"},
        {"query_scope": "Collection", "properties": "(country ASC, __name__ ASC)"},
    ]
}

// Output query status
{
    "resultsReturned": "1200",
    "executionDuration": "0.118882s",
    "readOperations": "1200",
    "debugStats": {
               "index_entries_scanned": "16500",
               "documents_scanned": "1200"
               "billing_details": {
                     "documents_billable": "1200",
                     "index_entries_billable": "0",
                     "small_ops": "0",
                     "min_query_cost": "0",
               }
    }
}

Untuk mengoptimalkan performa eksekusi kueri, Anda dapat membuat indeks gabungan yang tercakup sepenuhnya (category ASC, country ASC, __name__ ASC).

Dengan menjalankan kueri menggunakan opsi analisis lagi, kita dapat melihat bahwa indeks yang baru dibuat dipilih untuk kueri ini, dan kueri berjalan jauh lebih cepat dan lebih efisien.

// Output query planning info
{
    "indexes_used": [
        {"query_scope": "Collection", "properties": "(category ASC, country ASC,  __name__ ASC)"}
    ]
}

// Output query stats
{
    "resultsReturned": "1200",
    "executionDuration": "0.026139s",
    "readOperations": "1200",
    "debugStats": {
               "index_entries_scanned": "1200",
               "documents_scanned": "1200"
               "billing_details": {
                     "documents_billable": "1200",
                     "index_entries_billable": "0",
                     "small_ops": "0",
                     "min_query_cost": "0",
               }
    }
}