使用查詢說明功能瞭解查詢效能

透過查詢說明,您可以將 Cloud Firestore 查詢提交至後端,並接收有關後端查詢執行作業的詳細效能統計資料。其功能與許多關聯資料庫系統中的 EXPLAIN [ANALYZE] 作業類似。

您可以使用 Firestore 伺服器用戶端程式庫傳送查詢說明要求。

「查詢解釋結果」可協助您瞭解查詢的執行方式,顯示效率不佳及可能的伺服器端瓶頸位置。

查詢說明:

  • 提供有關查詢規劃階段的深入分析資訊,以便調整查詢索引並提高效率。
  • 使用分析選項,有助您瞭解個別查詢的費用和效能,並快速疊代不同的查詢模式,將用量最佳化。

瞭解查詢說明選項:預設與分析

您可以使用 default 選項或 analyze 選項執行查詢說明作業。

若使用預設選項,Query Explain 會規劃查詢,但會略過執行階段。系統隨即會傳回規劃工具的階段資訊。您可以使用此屬性來檢查查詢是否具有必要的索引,並瞭解使用的是哪些索引。舉例來說,如果某查詢使用複合式索引,而必須跨多個不同的索引建立交集,這將有助於您進行驗證。

使用分析選項時,「Query Explain」可說明兩個計畫並執行查詢。這會傳回先前提及的所有規劃工具資訊,以及查詢執行執行階段的統計資料。包括查詢的帳單資訊,以及查詢執行作業的系統層級深入分析資訊。您可以使用這項工具測試各種查詢和索引設定,盡可能提高成本效益與延遲時間。

什麼是查詢說明費用?

搭配使用查詢說明和預設選項時,系統不會執行索引或讀取作業。無論查詢的複雜度為何,系統都會收取一項讀取作業的費用。

當您在查詢說明中使用分析選項時,系統會執行索引和讀取作業,因此系統會如往常向您收取查詢費用。分析活動不會產生額外費用,只有執行查詢的平常費用才會計費。

以預設選項使用查詢說明

您可以使用用戶端程式庫提交預設選項要求。

請注意,要求是以 IAM 進行驗證,在一般查詢作業中使用相同的權限。但會忽略 Firebase 驗證等其他驗證技術。詳情請參閱適用於伺服器用戶端程式庫的 IAM 指南。

Java (管理員)

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();

    
節點 (管理員)

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;

    

回應的確切格式視執行環境而定。傳回的結果可轉換為 JSON。例如:

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

詳情請參閱查詢說明報表參考資料

搭配分析選項使用查詢說明

您可以使用用戶端程式庫提交分析選項要求。

請注意,要求是以 IAM 進行驗證,在一般查詢作業中使用相同的權限。但會忽略 Firebase 驗證等其他驗證技術。詳情請參閱適用於伺服器用戶端程式庫的 IAM 指南。

Java (管理員)

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();

    
節點 (管理員)

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;

    

以下範例顯示除了 planInfo 以外,系統傳回的 stats 物件。回應的確切格式視執行環境而定。回應範例會採用 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",
               }
    }

}

詳情請參閱查詢說明報表參考資料

解讀結果並進行調整

讓我們看看以下情境範例,我們按照製作影片的類型和國家/地區查詢電影。

為方便說明,假設這個 SQL 查詢相當於這個 SQL 查詢。

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

如果我們使用分析選項,傳回的指標會顯示查詢會在兩個單一欄位索引 ((category ASC, __name__ ASC)(country ASC, __name__ ASC)) 上執行。掃描 16500 個索引項目,但只會傳回 1200 個文件。

// 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",
               }
    }
}

如要最佳化執行查詢的效能,您可以建立全方位的複合式索引 (category ASC, country ASC, __name__ ASC)

再次使用分析選項執行查詢時,我們發現系統會為這項查詢選取新建立的索引,因此查詢的執行速度和執行速度會更快。

// 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",
               }
    }
}