סוגי אינדקסים ב-Cloud Firestore

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

בדף הזה מתוארים שני סוגי האינדקסים שבהם משתמשים ב-Cloud Firestore: אינדקסים אוטומטיים ואינדקסים ידניים.

הגדרה ומבנה של אינדקס

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

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

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

אינדקס מאחורי כל שאילתה

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

פחות ניהול אינדקסים, יותר פיתוח אפליקציות

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

סוגי אינדקסים

ב-Cloud Firestore יש שני סוגים של אינדקסים: אוטומטיים וידניים. יש הבדל בין אינדקסים ידניים לאוטומטיים באופן הניהול שלהם.

אינדקסים אוטומטיים

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

הגדרות ברירת המחדל של אינדקס אוטומטי

ב-Cloud Firestore נעשה שימוש בהגדרות ברירת המחדל הבאות לאינדקסים אוטומטיים:

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

  • לכל שדה במפה, Cloud Firestore יוצר את הדברים הבאים:

    • אינדקס אחד בסדר עולה ברמת האוסף לכל שדה משנה שהוא לא מערך ולא מפה.
    • אינדקס אחד בסדר יורד ברמת האוסף לכל שדה משנה שהוא לא מערך ולא מפה.
    • אינדקס אחד בסדר עולה ברמת האוסף לכל ערך המפה
    • אינדקס אחד בסדר יורד ברמת האוסף לכל ערך המפה
    • אינדקס array-contains אחד ברמת האוסף לכל שדה משנה של מערך.
    • ‫Cloud Firestore מוסיף לאינדקס באופן רקורסיבי כל שדה משנה של מפה.
  • לכל שדה מערך במסמך, Cloud Firestore יוצר את הדברים הבאים:

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

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

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

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

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

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

אינדקסים ידניים

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

ב-Cloud Firestore נעשה שימוש באינדקסים ידניים כדי לתמוך בשאילתות שלא נתמכות על ידי אינדקסים אוטומטיים.

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

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

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

מצבי אינדקס והיקפי שאילתות

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

מצבי אינדקס

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

מצב אינדקס תיאור
סדר עולה תומך בסעיפי השאילתה <,‏ <=,‏ ==,‏ >=,‏ >,‏ !=,‏ in ו-not-in בשדה, ותומך במיון התוצאות בסדר עולה על סמך ערך השדה הזה.
סדר יורד תומך בסעיפי השאילתה <, ‏ <=, ‏ ==, ‏ >=, ‏ >, ‏ !=, ‏ in ו-not-in בשדה, ותומך במיון התוצאות בסדר יורד על סמך ערך השדה הזה.
Array‑contains תומך בסעיפי השאילתה array-contains ו-array-contains-any בשדה.
וקטור תומך בסעיפי שאילתה מסוג FindNearest בשדה.

היקפי הרשאות של שאילתות

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

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

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

סידור אוטומטי והשדה __name__

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

כברירת מחדל, השדה __name__ ממוין באותו כיוון של השדה האחרון שמוין בהגדרת האינדקס. לדוגמה:

איסוף שדות שנוספו לאינדקס היקף השאילתה
ערים name, __name__ איסוף
ערים , __name__ איסוף
ערים ‫ מדינה, אוכלוסייה, __name__ איסוף

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

מאפייני אינדקס

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

  • שדות שמשמשים במסנני שוויון
  • שדות שמשמשים בסדרי מיון
  • שדות שמשמשים במסנני טווח ואי-שוויון (שעדיין לא נכללים בסדרי המיון)
  • שדות שמשמשים לצבירות (שעדיין לא נכללים בסדרי מיון ובמסננים של טווחים ואי-שוויון)

‫Cloud Firestore מחשב את תוצאות השאילתות באופן הבא:

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

דוגמה להוספה לאינדקס

יצירה אוטומטית של אינדקסים לשדה יחיד ב-Cloud Firestore מאפשרת לאפליקציה לתמוך במהירות בשאילתות הבסיסיות ביותר של מסד הנתונים. אינדקסים של שדה יחיד מאפשרים לבצע שאילתות פשוטות על סמך ערכי שדות והאופרטורים להשוואה <,‏ <=,‏ ==,‏ >=,‏ > ו-in. בשדות של מערכים, הם מאפשרים לבצע שאילתות של array-contains ו-array-contains-any.

כדי להמחיש, נבחן את הדוגמאות הבאות מנקודת המבט של יצירת אינדקס. קטע הקוד הבא יוצר כמה מסמכי city באוסף cities ומגדיר את השדות name,‏ state,‏ country,‏ capital,‏ population ו-regions לכל מסמך:

אינטרנט
var citiesRef = db.collection("cities");

citiesRef.doc("SF").set({
    name: "San Francisco", state: "CA", country: "USA",
    capital: false, population: 860000,
    regions: ["west_coast", "norcal"] });
citiesRef.doc("LA").set({
    name: "Los Angeles", state: "CA", country: "USA",
    capital: false, population: 3900000,
    regions: ["west_coast", "socal"] });
citiesRef.doc("DC").set({
    name: "Washington, D.C.", state: null, country: "USA",
    capital: true, population: 680000,
    regions: ["east_coast"] });
citiesRef.doc("TOK").set({
    name: "Tokyo", state: null, country: "Japan",
    capital: true, population: 9000000,
    regions: ["kanto", "honshu"] });
citiesRef.doc("BJ").set({
    name: "Beijing", state: null, country: "China",
    capital: true, population: 21500000,
    regions: ["jingjinji", "hebei"] });

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

איסוף השדה נוסף לאינדקס היקף השאילתה
ערים שם איסוף
ערים מדינה אחת () איסוף
ערים מדינה אחת () איסוף
ערים הון של איסוף
ערים אוכלוסיית איסוף
ערים ‫ אזורים איסוף
ערים שם איסוף
ערים מדינה אחת () איסוף
ערים מדינה אחת () איסוף
ערים הון של איסוף
ערים אוכלוסיית איסוף
ערים ‫ אזורים איסוף
ערים ‫array-contains אזורים איסוף

שאילתות שנתמכות על ידי אינדקסים של שדה יחיד

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

אינטרנט
const stateQuery = citiesRef.where("state", "==", "CA");
const populationQuery = citiesRef.where("population", "<", 100000);
const nameQuery = citiesRef.where("name", ">=", "San Francisco");

אפשר גם ליצור שאילתות in ושאילתות שוויון מורכבות (==):

אינטרנט
citiesRef.where('country', 'in', ["USA", "Japan", "China"])

// Compound equality queries
citiesRef.where("state", "==", "CO").where("name", "==", "Denver")
citiesRef.where("country", "==", "USA")
         .where("capital", "==", false)
         .where("state", "==", "CA")
         .where("population", "==", 860000)

אם אתם צריכים להריץ שאילתה מורכבת שמשתמשת בהשוואת טווחים (<,‏ <=,‏ > או >=) או אם אתם צריכים למיין לפי שדה אחר, אתם צריכים ליצור אינדקס ידני לשאילתה הזו.

האינדקס array-contains מאפשר לשלוח שאילתות לשדה המערך regions:

אינטרנט
citiesRef.where("regions", "array-contains", "west_coast")
// array-contains-any and array-contains use the same indexes
citiesRef.where("regions", "array-contains-any", ["west_coast", "east_coast"])

שאילתות שנתמכות על ידי אינדקסים ידניים

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

אינטרנט
citiesRef.where("country", "==", "USA").orderBy("population", "asc")
citiesRef.where("country", "==", "USA").where("population", "<", 3800000)
citiesRef.where("country", "==", "USA").where("population", ">", 690000)
// in and == clauses use the same index
citiesRef.where("country", "in", ["USA", "Japan", "China"])
         .where("population", ">", 690000)

השאילתות האלה דורשות את האינדקס הבא. מכיוון שהשאילתה משתמשת בשוויון (== או in) בשדה country, אפשר להשתמש במצב אינדקס בסדר עולה או יורד בשדה הזה. כברירת מחדל, סעיפי אי-שוויון מחילים סדר מיון עולה על סמך השדה בסעיף אי-השוויון.

איסוף שדות שנוספו לאינדקס היקף השאילתה
ערים (או ) מדינה, אוכלוסייה של איסוף

כדי להריץ את אותן שאילתות אבל בסדר יורד, צריך אינדקס נוסף בסדר יורד בשביל population:

אינטרנט
citiesRef.where("country", "==", "USA").orderBy("population", "desc")

citiesRef.where("country", "==", "USA")
         .where("population", "<", 3800000)
         .orderBy("population", "desc")

citiesRef.where("country", "==", "USA")
         .where("population", ">", 690000)
         .orderBy("population", "desc")

citiesRef.where("country", "in", ["USA", "Japan", "China"])
         .where("population", ">", 690000)
         .orderBy("population", "desc")
איסוף שדות שנוספו לאינדקס היקף השאילתה
ערים מדינה אחת (), אוכלוסייה: איסוף
ערים מדינה, אוכלוסייה איסוף

כדי למנוע פגיעה בביצועים כתוצאה ממיזוג אינדקסים, מומלץ ליצור אינדקס שישלב שאילתת array-contains או array-contains-any עם משפטים נוספים:

אינטרנט
citiesRef.where("regions", "array-contains", "east_coast")
         .where("capital", "==", true)

// array-contains-any and array-contains use the same index
citiesRef.where("regions", "array-contains-any", ["west_coast", "east_coast"])
         .where("capital", "==", true)
איסוף שדות שנוספו לאינדקס היקף השאילתה
ערים array-contains tags, (or ) capital איסוף

שאילתות שנתמכות על ידי אינדקסים של קבוצות אוספים

כדי להדגים אינדקס עם היקף של קבוצת אוספים, מוסיפים אוסף משנה של landmarks לחלק מהמסמכים של city:

אינטרנט
var citiesRef = db.collection("cities");

citiesRef.doc("SF").collection("landmarks").doc().set({
    name: "Golden Gate Bridge",
    category : "bridge" });
citiesRef.doc("SF").collection("landmarks").doc().set({
    name: "Golden Gate Park",
    category : "park" });

citiesRef.doc("DC").collection("landmarks").doc().set({
    name: "National Gallery of Art",
    category : "museum" });
citiesRef.doc("DC").collection("landmarks").doc().set({
    name: "National Mall",
    category : "park" });

באמצעות האינדקס הבא של שדה יחיד עם היקף של אוסף, אפשר לשלוח שאילתה לאוסף landmarks של עיר אחת על סמך השדה category:

איסוף שדות שנוספו לאינדקס היקף השאילתה
ציוני דרך קטגוריה (או ) איסוף
אינטרנט
citiesRef.doc("SF").collection("landmarks").where("category", "==", "park")
citiesRef.doc("SF").collection("landmarks").where("category", "in", ["park", "museum"])

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

איסוף שדות שנוספו לאינדקס היקף השאילתה
ציוני דרך קטגוריה (או ) קבוצת אוספים

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

אינטרנט
var landmarksGroupRef = db.collectionGroup("landmarks");

landmarksGroupRef.where("category", "==", "park")
landmarksGroupRef.where("category", "in", ["park", "museum"])

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

לדוגמה, אפשר להריץ את השאילתה הבאה של קבוצת אוספים בלי להפעיל אינדקס נוסף:

אינטרנט
db.collectionGroup("landmarks").get()

ערכים באינדקס

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

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

מסמך

/cities/SF

city_name : "San Francisco"
temperatures : {summer: 67, winter: 55}
neighborhoods : ["Mission", "Downtown", "Marina"]

אינדקסים אוטומטיים

  • city_name ASC
  • city_name DESC
  • שכונות בסדר עולה
  • שכונות בסדר יורד
  • טמפרטורות בסדר עולה
  • temperatures DESC
  • temperatures.summer ASC
  • temperatures.summer DESC
  • temperatures.winter ASC
  • temperatures.winter DESC
  • neighborhoods Array Contains

אינדקסים ידניים

  • city_name ASC, neighborhoods ARRAY
  • city_name DESC, neighborhoods ARRAY

ערכים באינדקס

הגדרת ההוספה לאינדקס הזו יוצרת את הרשומות הבאות באינדקס של המסמך:

אינדקס נתונים שנוספו לאינדקס
ערכי אינדקס אוטומטיים
city_name ASC city_name: "San Francisco"
city_name DESC city_name: "San Francisco"
שכונות בסדר עולה neighborhoods: ["Mission", "Downtown", "Marina"]
שכונות בסדר יורד neighborhoods: ["Mission", "Downtown", "Marina"]
טמפרטורות בסדר עולה temperatures: {summer: 67, winter: 55}‎
temperatures DESC temperatures: {summer: 67, winter: 55}‎
temperatures.summer ASC temperatures.summer: 67
temperatures.summer DESC temperatures.summer: 67
temperatures.winter ASC temperatures.winter: 55
temperatures.winter DESC temperatures.winter: 55
neighborhoods Array Contains שכונות: "מישן"
neighborhoods Array Contains neighborhoods: "Downtown"
neighborhoods Array Contains שכונות: "מרינה"
ערכי אינדקס ידניים
city_name ASC, neighborhoods ARRAY city_name: "San Francisco", neighborhoods: "Mission"
city_name ASC, neighborhoods ARRAY city_name: "San Francisco", neighborhoods: "Downtown"
city_name ASC, neighborhoods ARRAY city_name: "San Francisco", neighborhoods: "Marina"
city_name DESC, neighborhoods ARRAY city_name: "San Francisco", neighborhoods: "Mission"
city_name DESC, neighborhoods ARRAY city_name: "San Francisco", neighborhoods: "Downtown"
city_name DESC, neighborhoods ARRAY city_name: "San Francisco", neighborhoods: "Marina"

מדדים ותמחור

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

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

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

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

  • מסעדות

    • burgerthyme

      name : "Burger Thyme"
      category : "burgers"
      city : "San Francisco"
      editors_pick : true
      star_rating : 4

האפליקציה הזו משתמשת בשאילתות כמו זו שבהמשך. האפליקציה משתמשת בשילובים של משפטי שוויון ל-category, ל-city ול-editors_pick, וממיינת תמיד לפי star_rating בסדר עולה:

אינטרנט
db.collection("restaurants").where("category", "==", "burgers")
                            .orderBy("star_rating")

db.collection("restaurants").where("city", "==", "San Francisco")
                            .orderBy("star_rating")

db.collection("restaurants").where("category", "==", "burgers")
                            .where("city", "==", "San Francisco")
                            .orderBy("star_rating")

db.collection("restaurants").where("category", "==", "burgers")
                            .where("city", "==", "San Francisco")
                            .where("editors_pick", "==", true )
                            .orderBy("star_rating")

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

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

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

איסוף שדות שנוספו לאינדקס היקף השאילתה
מסעדות קטגוריה: , דירוג כוכבים: איסוף
מסעדות ‫ עיר, דירוג כוכבים איסוף
מסעדות editors_pick, star_rating איסוף

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

אינטרנט
db.collection("restaurants").where("editors_pick", "==", true)
                            .orderBy("star_rating")

מגבלות על הוספה לאינדקס

המגבלות הבאות חלות על אינדקסים. מידע נוסף על מכסות ומגבלות

מגבלה פרטים
המספר המקסימלי של אינדקסים מורכבים במסד נתונים
מספר מקסימלי של הגדרות שדה יחיד למסד נתונים
  • ‫200 אם לא הפעלתם את החיוב בפרויקט Google Cloud.

    אם אתם צריכים להגדיל את המכסה, אתם צריכים להפעיל את החיוב בפרויקט Google Cloud.

  • ‫1,000 כשמפעילים את החיוב בפרויקט Google Cloud.

הגדרה אחת ברמת השדה יכולה להכיל כמה הגדרות לאותו שדה. לדוגמה, החרגה של הוספה לאינדקס של שדה יחיד ומדיניות TTL באותו שדה נחשבות כהגדרה אחת של שדה במגבלה.

מספר הערכים המקסימלי באינדקס לכל מסמך

40,000

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

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

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

מספר השדות המקסימלי באינדקס מורכב 100
הגודל המקסימלי של רשומה באינדקס

7.5 KiB

כדי לראות איך Cloud Firestore מחשב את גודל הרשומה באינדקס, קראו את המאמר גודל הרשומה באינדקס.

הסכום המקסימלי של הגדלים של רשומות האינדקס של מסמך

8 MiB

הגודל הכולל הוא הסכום של הערכים הבאים במסמך:

  • סכום הגודל של רשומות האינדקס של שדה יחיד במסמך
  • סכום הגודל של רשומות האינדקס המורכב של מסמך
  • הגודל המקסימלי של ערך שדה שנוסף לאינדקס

    ‫1,500 בייטים

    ערכי שדות שגדולים מ-1,500 בייטים נחתכים. שאילתות שכוללות ערכי שדות חתוכים עשויות להחזיר תוצאות לא עקביות.

    שיטות מומלצות להוספה לאינדקס

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

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

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

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

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

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

    שדות TTL

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

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

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

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

    מידע נוסף על פתרון בעיות בהוספה לאינדקס (הוספה לאינדקס של מספר רב של ישויות, שגיאות INVALID_ARGUMENT) זמין בדף פתרון הבעיות.