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

כדי לפתור בעיות שקשורות לשאילתות איטיות, משתמשים ב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

אתם יכולים להשתמש ב-Query Explain, במיוחד באפשרות analyze, כדי לראות את ההשפעות של forceIndex:

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

שיטות מומלצות להשגת היעד forceIndex

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

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