אופטימיזציה של ביצועי השאילתות

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

הגבלת מספר התוצאות

כדי לדעת אם השאילתה מחזירה הרבה מסמכים, אפשר להשתמש בשדה records returned (רשומות שהוחזרו) בעץ הביצוע. כדאי להגביל את מספר המסמכים שמוחזרים באמצעות השלב limit(...). כך מקטינים את גודל הבייטים של התוצאות בסדרות כשמחזירים אותן ללקוחות ברשת. במקרים שבהם הצומת Limit קודם לצומת MajorSort, מנוע השאילתות יכול לאחד את הצמתים Limit ו-MajorSort ולהחליף מימוש מלא בזיכרון ומיון במיון TopN, וכך להקטין את דרישת הזיכרון של השאילתה.

הגבלת גודל המסמך של התוצאה

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

שימוש באינדקסים

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

זיהוי אם השאילתה משתמשת באינדקס

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

זיהוי מדד טוב יותר

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

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

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

יצירת אינדקסים

פועלים לפי ההוראות בתיעוד לניהול אינדקסים כדי ליצור אינדקסים. כדי לוודא שהשאילתה יכולה להשתמש באינדקסים, צריך ליצור אינדקסים רגילים (לא Multikey) עם שדות בסדר הבא:

  1. כל השדות שישמשו באופרטורים של שוויון. כדי למקסם את הסיכוי לשימוש חוזר בשאילתות, כדאי לסדר את השדות בסדר יורד לפי מספר הפעמים שהם מופיעים באופרטורים של שוויון בין השאילתות.
  2. כל השדות שייכללו במיון (באותו הסדר).
  3. שדות שישמשו באופרטורים של טווח או אי-שוויון בסדר יורד של סלקטיביות אילוצי השאילתה.
  4. שדות שיוחזרו כחלק משאילתה באינדקס: הכללת שדות כאלה באינדקס מאפשרת לאינדקס לכסות את השאילתה, וכך לא צריך לאחזר את המסמך מהאחסון הראשי.

אילוץ סריקה של אינדקס או טבלה

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

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

אפשר להשתמש באפשרות forceIndex בכל שלב קלט בפעולות של צינורות כדי לבטל את תוכנית השאילתה שמוגדרת כברירת מחדל ב-Cloud Firestore ולציין אינדקס לשימוש, או כדי לאלץ סריקה של טבלה.

אילוץ של אינדקס ספציפי

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

בדוגמה הבאה, המתכנן נאלץ להשתמש באינדקס עם המזהה CICAgOi36pgK:

Node.js
// Force Planner to use Index ID CICAgOi36pgK
await db.pipeline()
  .collectionGroup({ collectionId: "customers", forceIndex: "CICAgOi36pgK" })
  .limit(100)
  .execute();
Java
// Force Planner to use Index ID CICAgOi36pgK
Pipeline.Snapshot results1 =
    firestore.pipeline()
      .collectionGroup("customers", new CollectionGroupOptions()
          .withHints(new CollectionHints().withForceIndex("CICAgOi36pgK")))
      .limit(100)
      .execute().get();
המשך
// Force Planner to use Index ID CICAgOi36pgK
snapshot1 := client.Pipeline().
	CollectionGroup("customers", firestore.WithForceIndex("CICAgOi36pgK")).
	Limit(100).
	Execute(ctx)

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

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

אם האינדקס שצוין לא נמצא, השאילתה נכשלת.

אילוץ סריקת טבלה

סריקת טבלה קוראת מסמכים באוסף או בקבוצת אוספים בלי להשתמש באינדקסים משניים. כדי לכפות סריקת טבלה, מגדירים את forceIndex לערך primary.

בדוגמה הבאה מתבצעת סריקת טבלה:

// Force Planner to only do a Full-Table Scan
db.pipeline()
  .collectionGroup({ collectionId: "customers", forceIndex: "primary" })
  .limit(100)

יכול להיות שתשתמשו בסריקת טבלה במקרים הבאים:

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

שימוש ב-forceIndex עם Query Explain

אפשר להשתמש בהסבר על שאילתה במצבים explain או analyze כדי לראות את ההשפעות של forceIndex:

  • כדי לוודא ש-Cloud Firestore השתמש באינדקס שצוין ב-forceIndex, צריך לבדוק את צמתי העלה של עץ הביצוע כדי למצוא את מזהה האינדקס.
  • מוודאים שצומת TableScan מופיע בתוכנית כשמשתמשים ב-forceIndex: "primary".
  • במצב analyze, אפשר להשוות בין מדדי הביצועים – כמו זמן האחזור, המסמכים שנסרקו והערכים באינדקס שנסרקו – עם forceIndex ובלי, כדי לשפר את ביצועי השאילתות.

שיטות מומלצות לשימוש בforceIndex

למרות ש-forceIndex מספקת יותר שליטה על ביצוע השאילתות, Cloud Firestoreאופטימיזציית השאילתות של בדרך כלל יעילה לרוב תרחישי השימוש. כדאי לפעול לפי השיטות המומלצות הבאות כשמשתמשים ב-forceIndex:

  • חשוב להשתמש ב-forceIndex בחוכמה. אם אתם רואים שהביצועים לא אופטימליים עם תוכנית לביצוע שאילתה שמוגדרת כברירת מחדל, כדאי להשתמש בהסבר על שאילתה כדי לאבחן את הבעיה לפני שמכריחים שימוש באינדקס.
  • כשמשתמשים ב-forceIndex, חשוב לבדוק את השאילתות עם נפחי נתונים ריאליים כדי להבין את מאפייני הביצועים והעלות שלהן.
  • מומלץ להימנע משימוש ב-forceIndex: "primary" באוספים גדולים בסביבות ייצור.

מידע נוסף על הפלט של שאילתה שהופעלה באמצעות Query Explain זמין במאמר הפניה להפעלת שאילתות.