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

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

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

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

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

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

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

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

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

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

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

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

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

אינדקסים של שדה יחיד

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

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

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

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

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

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

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

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

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

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

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

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

אינדקסים מורכבים

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

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

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

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

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

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

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

מצבי אינדקס

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

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

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

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

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

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

סדר ברירת המחדל והשדה __name__

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

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

איסוף שדות שנוספו לאינדקס היקף השאילתה
ערים name,‏ __name__ איסוף
ערים המצב , __name__ איסוף
ערים country,‏ population,‏ __name__ איסוף

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

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

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

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

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

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

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

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

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

אינטרנט
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 אזורים איסוף

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

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

אינטרנט
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"])

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

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

אינטרנט
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")
איסוף שדות שנוספו לאינדקס היקף השאילתה
ערים country, ‏ population איסוף
cities country, ‏ population איסוף

כדי למנוע ירידה בביצועים שנגרמת כתוצאה ממיזוג של אינדקסים, מומלץ ליצור אינדקס מורכב כדי לשלב שאילתה מסוג 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, (או ) באותיות רישיות איסוף

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

כדי להדגים אינדקס ברמת קבוצת האוספים, מוסיפים אוסף משנה מסוג 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()

רשומות אינדקס

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

הדוגמה הבאה ממחישה את הרשומות של המסמך ב-Index.

מסמך

/cities/SF

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

אינדקסים של שדה יחיד

  • city_name ASC
  • city_name DESC
  • temperatures.summer ASC
  • temperatures.summer DESC
  • temperatures.winter ASC
  • טמפרטורות.winter – תיאור
  • מערך השכונות מכיל (ASC ו-DESC)

אינדקסים מורכבים

  • City_name ASC, שכונות ARRAY
  • city_name DESC,‏ neighborhoods ARRAY

רשומות אינדקס

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

אינדקס נתונים שנוספו לאינדקס
רשומות של מדדים עם שדה יחיד
city_name ASC city_name: "San Francisco"
city_name DESC city_name: "San Francisco"
temperatures.summer ASC טמפרטורות.קיץ: 67
טמפרטורות.קיץ: תיאור טמפרטורות.קיץ: 67
temperatures.winter ASC temperatures.winter:‏ 55
temperatures.winter DESC temperatures.winter:‏ 55
מערך השכונות מכיל ASC שכונות: "Mission"
שכונות מערך שמכיל את DESC שכונות: "משימה"
שכונות מערך מכיל ASC שכונות: "מרכז העיר"
מערך השכונות מכיל DESC שכונות: 'מרכז העיר'
שכונות מערך מכיל ASC שכונות: "Marina"
מערך השכונות מכיל DESC שכונות: "Marina"
רשומות של אינדקס מורכב
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"
עיר_name DESC, שכונות ARRAY City_name: "מודיעין", שכונות: "מיסיון"
עיר_name DESC, שכונות ARRAY city_name:‏ "San Francisco",‏ neighborhoods:‏ "Downtown"
עיר_name DESC, שכונות ARRAY city_name:‏ "San Francisco", ‏ neighborhoods:‏ "Marina"

מדדים ותמחור

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

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

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

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

  • מסעדות

    • המבורגר

      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")

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

איסוף שדות שנוספו לאינדקס היקף השאילתה
מסעדות category,‏ star_rating איסוף
מסעדות עיר אחת (), דירוג_כוכבים אחד () איסוף
מסעדות category, ‏ city, ‏ star_rating איסוף
מסעדות category,‏ city,‏ editors_pick,‏ star_rating איסוף

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

איסוף שדות שנוספו לאינדקס היקף השאילתה
מסעדות category,‏ star_rating איסוף
מסעדות עיר אחת (), דירוג_כוכבים אחד () איסוף
מסעדות editors_pick,‏ star_rating איסוף

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

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

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

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

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

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

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

40,000

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

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

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

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

7.5 KiB

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

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

8MiB

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

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

    1,500 בייטים

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

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

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

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

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

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

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

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

    שדות TTL

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

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

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

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

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