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

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

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

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

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

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

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

אפשר לבצע פעולות של הסבר שאילתות באמצעות האפשרות ברירת מחדל או באמצעות האפשרות ניתוח.

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

כשמשתמשים באפשרות analyze, 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';

אם נשתמש באפשרות analyze, המדדים שיוחזרו יראו שהשאילתה פועלת בשני אינדקסים של שדה יחיד, (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",
               }
    }
}