שיטות מומלצות עבור Cloud Firestore

אתם יכולים להשתמש בשיטות המומלצות שמפורטות כאן כחומר עזר קצר כשמפתחים אפליקציה שמשתמשת ב-Cloud Firestore.

מיקום מסד הנתונים

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

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

בוחרים מיקום אזורי לעלויות נמוכות יותר לצורך כתיבה אם האפליקציה שלכם רגישה לזמן אחזור, או למיקום משותף עם משאבים אחרים של GCP.

מזהי מסמכים

  • מומלץ להימנע ממזהי המסמכים . ו-...
  • הימנעו משימוש בקו נטוי קדימה / במזהי מסמכים.
  • אין להשתמש בהגדלת מזהי מסמכים באופן מונוטוני, כמו:

    • Customer1, Customer2, Customer3, ...
    • Product 1, Product 2, Product 3, ...

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

שמות שדות

  • מומלץ להימנע מהתווים הבאים בשמות השדות, כי הם דורשים תו בריחה נוסף:

    • תקופת .
    • [ סוגר מרובע שמאלי
    • ] סוגר מרובע ימני
    • כוכבית *
    • סימן דיאקריטי (`)

מדדים

מפחיתים את זמן האחזור לכתיבה

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

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

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

פטורים מהוספה לאינדקס

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

נרתיק תיאור
שדות מחרוזות גדולים

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

קצבי כתיבה גבוהים באוסף שמכיל מסמכים עם ערכים עוקבים

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

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

שדות TTL

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

שדות מפה או מערך גדולים

שדות גדולים של מפות או מערכי נתונים עלולים להגיע למגבלה של 40,000 רשומות באינדקס לכל מסמך. אם אתם לא שולחים שאילתות על סמך מערך גדול או שדה מפה, כדאי לפטור אותם מהוספה לאינדקס.

פעולות קריאה וכתיבה

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

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

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

ניסיונות חוזרים של עסקאות

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

עדכונים בזמן אמת

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

עיצוב בקנה מידה רחב

בשיטות המומלצות הבאות מוסבר איך להימנע ממצבים שיוצרים בעיות של תחרות על משאבים.

עדכונים למסמך יחיד

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

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

קצבי קריאה, כתיבה ומחיקה גבוהים בטווח מסמכים מצומצם

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

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

    Cloud Firestore מקצה מזהי מסמכים באמצעות אלגוריתם פיזור. אם תיצרו מסמכים חדשים באמצעות מזהי מסמכים אוטומטיים, לא אמורה להתרחש התמקדות בכתיבה (hotspotting).

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

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

  • מחיקה של מסמכים באוסף בקצב גבוה.

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

איך להימנע מדילוג על נתונים שנמחקו

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

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

docs = db.collection('WorkItems').order_by('created').limit(100)
delete_batch = db.batch()
for doc in docs.stream():
  finish_work(doc)
  delete_batch.delete(doc.reference)
delete_batch.commit()

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

כדי לשפר את הביצועים, כדאי להשתמש בשיטה start_at מקום להתחיל בו. לדוגמה:

completed_items = db.collection('CompletionStats').document('all stats').get()
docs = db.collection('WorkItems').start_at(
    {'created': completed_items.get('last_completed')}).order_by(
        'created').limit(100)
delete_batch = db.batch()
last_completed = None
for doc in docs.stream():
  finish_work(doc)
  delete_batch.delete(doc.reference)
  last_completed = doc.get('created')

if last_completed:
  delete_batch.update(completed_items.reference,
                      {'last_completed': last_completed})
  delete_batch.commit()

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

הגדלת נפח התנועה

עליכם להגביר את התנועה בהדרגה לאוספים חדשים או באופן לקסיקוגרפי לסגור מסמכים כדי לתת לCloud Firestore מספיק זמן להתכונן מסמכים כדי להגדיל את התנועה. מומלץ להתחיל עם 500 פעולות לכל היותר לשנייה בקולקציה חדשה, ולאחר מכן להגדיל את נפח התנועה ב-50% כל 5 דקות. אפשר להגדיל באופן דומה את תעבורת הכתיבה, אבל חשוב לזכור את המגבלות הסטנדרטיות של Cloud Firestore. חשוב שהפעולות יחולקו באופן שווה יחסית לאורך טווח המפתחות. הזה נקרא "500/50/5" כלל.

העברת תנועה לאוסף חדש

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

בעיה דומה יכולה להתרחש אם משנים את מזהי המסמכים של הרבה מסמכים באותו אוסף.

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

קריאות מקבילות

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

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

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

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

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

פרטיות

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

מניעת גישה לא מורשית

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

מידע נוסף על שימוש ב-Cloud Firestore Security Rules