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

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

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

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

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

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

הסבר על האפשרויות של 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).

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

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