הבנת ביצועי שאילתות באמצעות הסבר שאילתה

התכונה "הסבר על שאילתות" מאפשרת לשלוח שאילתות Cloud Firestore לקצה העורפי, ולקבל בתמורה נתונים סטטיסטיים מפורטים על ביצועי השאילתות בקצה העורפי. היא פועלת כמו הפעולה EXPLAIN [ANALYZE] בהרבה מערכות של מסדי נתונים רלציוניים.

אפשר לשלוח בקשות של Query Explain באמצעות ספריות הלקוח של שרת Firestore.

התוצאות של Query Explain עוזרות להבין איך השאילתות מבוצעות, ומציגות חוסר יעילות ואת המיקום של צווארי בקבוק אפשריים בצד השרת.

הסבר על השאילתה:

  • מספק תובנות לגבי שלב התכנון של השאילתה, כדי שתוכלו לשנות את האינדקסים של השאילתה ולשפר את היעילות.
  • בעזרת אפשרות הניתוח, תוכלו להבין את העלות והביצועים של כל שאילתה, ולעבור במהירות בין מבני שאילתות שונים כדי לבצע אופטימיזציה של השימוש בהם.

הסבר על האפשרויות של Query Explain: ברירת מחדל וניתוח

אפשר לבצע פעולות של הסבר שאילתה באמצעות האפשרות default או האפשרות analyze.

באפשרות ברירת המחדל, Query Explain מתכנן את השאילתה אבל מדלג על שלב ההרצה. הפעולה הזו תחזיר מידע על שלב התכנון. אתם יכולים להשתמש בזה כדי לבדוק אם לשאילתה יש את האינדקסים הדרושים ולהבין באילו אינדקסים נעשה שימוש. כך תוכלו לוודא, למשל, ששאילתה מסוימת משתמשת באינדקס מורכב במקום להצטלב עם הרבה אינדקסים שונים.

באפשרות הניתוח, Query Explain מתכנן ומריץ את השאילתה. הפעולה הזו מחזירה את כל המידע על המתכנן שהוזכר קודם, יחד עם נתונים סטטיסטיים מזמן הריצה של ביצוע השאילתה. המידע הזה יכלול את פרטי החיוב של השאילתה, יחד עם תובנות ברמת המערכת לגבי ביצוע השאילתה. אתם יכולים להשתמש בכלי הזה כדי לבדוק הגדרות שונות של שאילתות ואינדקסים, במטרה לשפר את העלות ואת זמן האחזור שלהם.

כמה עולה להשתמש ב-Query Explain?

כשמשתמשים ב-Query Explain עם אפשרות ברירת המחדל, לא מתבצעות פעולות אינדקס או קריאה. לא משנה כמה השאילתה מורכבת, החיוב הוא על פעולת קריאה אחת.

כשמשתמשים ב-Query Explain עם האפשרות analyze, מתבצעות פעולות אינדקס וקריאה, ולכן אתם מחויבים על השאילתה כרגיל. אין חיוב נוסף על פעילות הניתוח, אלא רק החיוב הרגיל על השאילתה שמופעלת.

שימוש ב-Query Explain עם אפשרות ברירת המחדל

אתם יכולים להשתמש בספריות הלקוח כדי לשלוח בקשה לאפשרות ברירת המחדל.

שימו לב שהבקשות מאומתות באמצעות IAM, עם אותן הרשאות לפעולות של שאילתות רגילות. המערכת מתעלמת משיטות אימות אחרות, כמו Firebase Authentication. מידע נוסף זמין במדריך בנושא 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)"},
    ]
}

מידע נוסף זמין בחומר העזר בנושא דוח Query Explain.

שימוש ב-Query Explain עם האפשרות analyze

אתם יכולים להשתמש בספריות הלקוח כדי לשלוח בקשה לניתוח אפשרויות.

שימו לב שהבקשות מאומתות באמצעות IAM, עם אותן הרשאות לפעולות של שאילתות רגילות. המערכת מתעלמת משיטות אימות אחרות, כמו Firebase Authentication. מידע נוסף זמין במדריך בנושא 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;

    

בדוגמה הבאה מוצג האובייקט stats שמוחזר בנוסף ל-planInfo. הפורמט המדויק של התגובה תלוי בסביבת ההפעלה. התגובה לדוגמה היא בפורמט 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",
               }
    }

}

מידע נוסף זמין בחומר העזר בנושא דוח Query Explain.

איך מפרשים את התוצאות ומבצעים שינויים

נבחן תרחיש לדוגמה שבו אנחנו שולחים שאילתה על סרטים לפי ז'אנר ומדינת הפקה.

לשם המחשה, נניח שזו שאילתת SQL המקבילה.

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

אם נשתמש באפשרות הניתוח, המדדים שיוחזרו יראו שהשאילתה פועלת על שני אינדקסים של שדה יחיד, (category ASC, __name__ ASC) ו-(country ASC, __name__ ASC). היא סורקת 16,500 רשומות באינדקס, אבל מחזירה רק 1,200 מסמכים.

// 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).

אם נריץ שוב את השאילתה עם האפשרות analyze, נראה שהאינדקס החדש נבחר לשאילתה הזו, והיא רצה הרבה יותר מהר וביעילות.

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