בעזרת Query Explain אפשר לשלוח שאילתות Cloud Firestore לקצה העורפי ולקבל נתונים סטטיסטיים מפורטים על ביצועי ביצוע השאילתות בקצה העורפי. היא פועלת כמו הפעולה EXPLAIN [ANALYZE]
בהרבה מערכות של מסדי נתונים יחסיים.
אפשר לשלוח בקשות של הסבר על שאילתות באמצעות ספריות הלקוח של שרת Firestore.
התוצאות של הסבר השאילתה עוזרות לכם להבין איך השאילתות מתבצעות ומראה לכם חוסר יעילות ואת המיקום של צווארי בקבוק בסבירות גבוהה בצד השרת.
הסבר את השאילתה:
- תובנות לגבי שלב תכנון השאילתה, כדי שתוכלו לשנות את אינדקסי השאילתות ולשפר את היעילות.
- בעזרת האפשרות 'ניתוח' תוכלו להבין את העלות והביצועים של כל שאילתה, ולעבור במהירות על דפוסי שאילתות שונים כדי לבצע אופטימיזציה של השימוש בהם.
הסבר על האפשרויות של Query Explain: ברירת מחדל וניתוח
אפשר לבצע פעולות של הסבר שאילתה באמצעות אפשרות ברירת המחדל או האפשרות ניתוח.
באפשרות ברירת המחדל, Query Explain מתכנן את השאילתה אבל מדלג על שלב ההפעלה. הפונקציה הזו תחזיר מידע על שלב התכנון. אפשר להשתמש בו כדי לבדוק אם לשאילתה יש את האינדקסים הנדרשים ולהבין באילו אינדקסים נעשה שימוש. כך תוכלו לוודא, לדוגמה, ששאילתה מסוימת משתמשת באינדקס מורכב, במקום להצטלב עם אינדקסים רבים ושונים.
באפשרות הניתוח, Query תסביר גם את התוכניות וגם תריץ את השאילתה. הפונקציה הזו מחזירה את כל המידע של הכלי לתכנון שצוין למעלה, יחד עם נתונים סטטיסטיים מזמן הריצה של השאילתה. הנתונים יכללו את נתוני החיוב של השאילתה, וגם תובנות ברמת המערכת לגבי ביצוע השאילתה. אפשר להשתמש בכלים האלה כדי לבדוק הגדרות שונות של שאילתות ומפתחות אינדקס, כדי לבצע אופטימיזציה של העלות וזמן האחזור שלהם.
מהי עלות הסבר לשאילתה?
כשמשתמשים ב-Query Explain עם אפשרות ברירת המחדל, לא מתבצעות פעולות של אינדקס או קריאה. ללא קשר למורכבות השאילתה, אנחנו מחייבים בפעולת קריאה אחת.
כשמשתמשים ב-Query Explain עם האפשרות analyze, מתבצעות פעולות של הוספה לאינדקס וקריאה, כך שתחויבו על השאילתה כרגיל. אין חיוב נוסף על פעילות הניתוח, רק החיוב הרגיל על השאילתה שמתבצעת.
שימוש ב'הסבר על שאילתה' עם אפשרות ברירת המחדל
אפשר להשתמש בספריות הלקוח כדי לשלוח בקשה לאפשרות ברירת המחדל.
חשוב לציין שהבקשות מאומתות באמצעות 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 עם האפשרות 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", } } }