בדף הזה מוסבר על מושגים שכדאי להכיר כשבוחרים אינדקסים של Firestore במצב Datastore לאפליקציה.
Firestore במצב Datastore מספק ביצועים גבוהים של שאילתות באמצעות שימוש באינדקסים לכל השאילתות. הביצועים של רוב השאילתות תלויים בגודל של קבוצת התוצאות ולא בגודל הכולל של מסד הנתונים.
ב-Firestore במצב Datastore מוגדרים אינדקסים מובנים לכל מאפיין בישות. האינדקסים האלה של נכס יחיד תומכים בהרבה שאילתות פשוטות. ב-Firestore במצב Datastore יש תכונה של מיזוג אינדקסים, שמאפשרת למסד הנתונים למזג אינדקסים מובנים כדי לתמוך בשאילתות נוספות. בשביל שאילתות מורכבות יותר, צריך להגדיר מראש אינדקסים מורכבים.
הדף הזה מתמקד בתכונה של מיזוג אינדקסים, כי היא משפיעה על שתי הזדמנויות חשובות לאופטימיזציה של אינדקסים:
- האצת השאילתות
- צמצום מספר האינדקסים המורכבים
בדוגמה הבאה אפשר לראות איך משתמשים בתכונה של מיזוג אינדקסים.
סינון ישויות Photo
כדאי לשקול שימוש במסד נתונים במצב Datastore עם ישויות מסוג Photo:
| תמונה | ||
|---|---|---|
| מאפיין (property) | סוג הערך | תיאור |
owner_id |
String | מזהה המשתמש |
tag |
מערך של מחרוזות | מילות מפתח שעברו טוקניזציה |
size |
מספר שלם |
מספור:
|
coloration |
מספר שלם |
מספור:
|
תארו לעצמכם שאתם צריכים תכונה באפליקציה שמאפשרת למשתמשים לשלוח שאילתות לגבי Photo
ישויות על סמך AND לוגיקה מהסוג הבא:
עד שלושה מסננים שמבוססים על המאפיינים:
owner_idsizecoloration
מחרוזת חיפוש ב-
tag. האפליקציה מבצעת טוקניזציה של מחרוזת החיפוש לתגים ומוסיפה מסנן לכל תג.לדוגמה, האפליקציה הופכת את מחרוזת החיפוש
outside, familyלשאילתת המסנניםtag=outsideו-tag=family.
באמצעות אינדקסים מובנים ותכונת מיזוג האינדקסים של Firestore במצב Datastore, אפשר לעמוד בדרישות האינדקס של תכונת הסינון Photo הזו בלי להוסיף אינדקסים מורכבים נוספים.
האינדקסים המובנים לישויות Photo תומכים בשאילתות עם מסנן יחיד כמו:
Python
תכונת הסינון Photo מחייבת גם שאילתות שמשלבות כמה מסנני שוויון עם לוגיקת AND:
Python
מערכת Firestore במצב Datastore יכולה לתמוך בשאילתות האלה על ידי מיזוג של אינדקסים מובנים.
מיזוג אינדקסים
ב-Firestore במצב Datastore, אפשר להשתמש במיזוג אינדקסים אם השאילתה והאינדקסים עומדים בכל האילוצים הבאים:
- השאילתה משתמשת רק במסננים של שוויון (
=) - לא קיים אינדקס מורכב שתואם באופן מושלם למסננים ולסדר של השאילתה
- כל מסנן שוויון תואם לפחות לאינדקס קיים אחד עם אותו סדר כמו השאילתה
במצב כזה, אפשר להשתמש באינדקסים קיימים ב-Firestore במצב Datastore כדי לתמוך בשאילתה, במקום להגדיר אינדקס מורכב נוסף.
כשממיינים שני אינדקסים או יותר לפי אותם קריטריונים, מערכת Firestore במצב Datastore יכולה למזג את התוצאות של סריקות של כמה אינדקסים כדי למצוא את התוצאות שמשותפות לכל האינדקסים האלה. אפשר למזג אינדקסים מובנים ב-Firestore במצב Datastore, כי כולם ממיינים את הערכים לפי מפתח הישות.
על ידי מיזוג של אינדקסים מובנים, Firestore במצב Datastore תומך בשאילתות עם מסנני שוויון בכמה מאפיינים:
Python
בנוסף, אפשר למזג ב-Firestore במצב Datastore תוצאות של אינדקס מכמה חלקים של אותו אינדקס. על ידי מיזוג של חלקים שונים באינדקס המובנה של המאפיין tag
, Firestore במצב Datastore תומך בשאילתות שמשלבות כמה מסננים tag
בצורה לוגית tag:AND
Python
השאילתות שנתמכות על ידי אינדקסים מוכללים שמוזגו משלימות את קבוצת השאילתות שנדרשות לתכונת הסינון Photo. שימו לב: כדי לתמוך בתכונת הסינון Photo
לא נדרשו אינדקסים מורכבים נוספים.
כשבוחרים את האינדקסים האופטימליים לאפליקציה, חשוב להבין את התכונה של מיזוג אינדקסים. מיזוג אינדקסים מעניק ל-Firestore במצב Datastore גמישות רבה יותר בשאילתות, אבל יכול להיות שיהיה לכך מחיר בביצועים. בקטע הבא מוסבר על הביצועים של מיזוג אינדקסים ואיך לשפר את הביצועים באמצעות הוספה של אינדקסים מורכבים.
איך מוצאים את האינדקס המושלם
האינדקס ממוין קודם לפי ישות אב ואז לפי ערכי מאפיינים, בסדר שצוין בהגדרת האינדקס. האינדקס המורכב המושלם לשאילתה, שמאפשר להריץ את השאילתה בצורה הכי יעילה, מוגדר במאפיינים הבאים, לפי הסדר:
- מאפיינים שמשמשים במסנני שוויון
- מאפיינים שמשמשים בסדר מיון
- מאפיינים שמשמשים לסינון
distinctOn - מאפיינים שמשמשים במסנני טווח ואי-שוויון (שלא נכללים כבר בסדר המיון)
- מאפיינים שמשמשים בצבירות ובתחזיות (שלא נכללים כבר בסדר מיון ובמסנני טווח ואי-שוויון)
כך אפשר לוודא שכל התוצאות של כל ביצוע אפשרי של השאילתה נלקחות בחשבון. מסדי נתונים של Firestore במצב Datastore מריצים שאילתה באמצעות אינדקס מושלם באופן הבא:
- מזהה את האינדקס שמתאים לסוג השאילתה, למאפייני המסנן, לאופרטורים של המסנן ולסדר המיון
- סריקה מתחילת האינדקס עד לישות הראשונה שעומדת בכל תנאי הסינון של השאילתה או בחלק מהם
- המערכת ממשיכה לסרוק את האינדקס ומחזירה כל ישות שעומדת בכל תנאי הסינון, עד שהיא
- נתקלתם בישות שלא עומדת בתנאי הסינון, או
- מגיע לסוף האינדקס, או
- הגיע למספר המקסימלי של התוצאות שנדרשו בשאילתה
לדוגמה, נניח את השאילתה הבאה:
SELECT * FROM Task
WHERE category = 'Personal'
AND priority < 3
ORDER BY priority DESC
האינדקס המורכב המושלם לשאילתה הזו הוא אינדקס של מפתחות לישויות מסוג Task, עם עמודות לערכים של המאפיינים category ו-priority. האינדקס ממוין קודם בסדר עולה לפי category ואז בסדר יורד לפי priority:
indexes:
- kind: Task
properties:
- name: category
direction: asc
- name: priority
direction: desc
שתי שאילתות באותו פורמט אבל עם ערכי מסנן שונים משתמשות באותו אינדקס. לדוגמה, השאילתה הבאה משתמשת באותו אינדקס כמו השאילתה הקודמת:
SELECT * FROM Task
WHERE category = 'Work'
AND priority < 5
ORDER BY priority DESC
לאינדקס הזה
indexes:
- kind: Task
properties:
- name: category
direction: asc
- name: priority
direction: asc
- name: created
direction: asc
האינדקס הקודם יכול לספק את התוצאות של שתי השאילתות הבאות:
SELECT * FROM Task
WHERE category = 'Personal'
AND priority = 5
ORDER BY created ASC
וגם
SELECT * FROM Task
WHERE category = 'Work'
ORDER BY priority ASC, created ASC
אופטימיזציה של בחירת האינדקס
בקטע הזה מתוארים מאפייני הביצועים של מיזוג אינדקסים ושתי הזדמנויות לאופטימיזציה שקשורות למיזוג אינדקסים:
- הוספת אינדקסים מורכבים כדי להאיץ שאילתות שמסתמכות על אינדקסים שמוזגו
- צריך לצמצם את מספר האינדקסים המורכבים באמצעות מיזוג אינדקסים
ביצועים של מיזוג אינדקסים
במיזוג אינדקסים, Firestore במצב Datastore ממזג אינדקסים בצורה יעילה באמצעות אלגוריתם מיזוג זיגזג. באמצעות האלגוריתם הזה, מצב Datastore מצטרף להתאמות פוטנציאליות מסריקות מרובות של אינדקסים כדי ליצור קבוצת תוצאות שתואמת לשאילתה. מיזוג אינדקסים משלב רכיבי סינון בזמן הקריאה ולא בזמן הכתיבה. בניגוד לרוב השאילתות ב-Firestore במצב Datastore, שבהן הביצועים תלויים רק בגודל של קבוצת התוצאות, הביצועים של שאילתות מיזוג אינדקסים תלויים במסננים בשאילתה ובמספר ההתאמות הפוטנציאליות שהמסד נתונים בודק.
הביצועים הכי טובים של מיזוג אינדקסים מתקבלים כשכל התאמה פוטנציאלית באינדקס עומדת במסנני השאילתה. במקרה הזה, הביצועים הם O(R * I)
כאשר R הוא גודל קבוצת התוצאות ו-I הוא מספר האינדקסים שנסרקו.
הביצועים במקרה הגרוע ביותר מתרחשים כשמסד הנתונים צריך לבדוק הרבה התאמות פוטנציאליות, אבל רק מעט מהן עומדות בדרישות של מסנני השאילתה. במקרה הזה, הביצועים הם O(S) כאשר S הוא הגודל של הקבוצה הקטנה ביותר של ישויות פוטנציאליות מסריקה של אינדקס יחיד.
הביצועים בפועל תלויים בצורת הנתונים. מספר הישויות הממוצע שנלקח בחשבון עבור כל תוצאה שהוחזרה הוא O(S/(R * I)). הביצועים של שאילתות נמוכים יותר כשהרבה ישויות תואמות לסריקת כל אינדקס, אבל מעט ישויות תואמות לשאילתה כולה. כלומר, R קטן ו-S גדול.
יש ארבע דרכים לצמצם את הסיכון הזה:
מתכנן השאילתות לא מחפש ישות עד שהוא יודע שהישות תואמת לשאילתה כולה.
האלגוריתם של הזיגזג לא צריך למצוא את כל התוצאות כדי להחזיר את התוצאה הבאה. אם מבקשים את 10 התוצאות הראשונות, משלמים רק על זמן האחזור של איתור 10 התוצאות האלה.
אלגוריתם הזיגזג מדלג על חלקים גדולים של תוצאות חיוביות שגויות. הביצועים במקרה הגרוע ביותר מתרחשים רק אם תוצאות חיוביות שגויות משולבות בצורה מושלמת (בסדר המיון) בין הסריקות.
זמן האחזור תלוי במספר הישויות שנמצאו בכל סריקה של אינדקס, ולא במספר הישויות שתואמות לכל מסנן. כפי שמוצג בקטע הבא, אפשר להוסיף אינדקסים מורכבים כדי לשפר את הביצועים של מיזוג האינדקסים.
האצת שאילתת מיזוג אינדקסים
כשאינדקסים ב-Firestore במצב Datastore עוברים מיזוג, כל סריקה של אינדקס ממופה בדרך כלל למסנן יחיד בשאילתה. כדי לשפר את הביצועים של שאילתות, אפשר להוסיף אינדקסים מורכבים שתואמים לכמה מסננים בשאילתה.
נניח שיש לכם את השאילתה הבאה:
Python
כל מסנן ממופה לסריקת אינדקס אחת באינדקסים המובנים הבאים:
Index(Photo, owner_id) Index(Photo, size) Index(Photo, tag)
אם מוסיפים את האינדקס המורכב Index(Photo, owner_id, size), השאילתה ממופה לשני סריקות אינדקס במקום לשלוש:
# Satisfies both 'owner_id=username' and 'size=2'
Index(Photo, owner_id, size)
Index(Photo, tag)תארו לעצמכם תרחיש עם הרבה תמונות גדולות, הרבה תמונות בשחור-לבן, אבל מעט תמונות פנורמיות גדולות. שאילתה שמסננת גם תמונות פנורמיות וגם תמונות בשחור-לבן תפעל לאט אם היא ממזגת אינדקסים מובנים:
Python
כדי לשפר את ביצועי השאילתות, אפשר להקטין את הערך של S (הקבוצה הקטנה ביותר של ישויות בסריקה של אינדקס יחיד) ב-O(S/(R * I)) על ידי הוספת האינדקס המורכב הבא:
Index(Photo, size, coloration)
בהשוואה לשימוש בשני אינדקסים מובנים, האינדקס המורכב הזה מפיק פחות תוצאות פוטנציאליות עבור אותם שני מסנני שאילתות. הגישה הזו משפרת משמעותית את הביצועים, אבל היא דורשת עוד אינדקס.
צמצום מספר האינדקסים המורכבים באמצעות מיזוג אינדקסים
למרות שמדדים מורכבים שתואמים בדיוק למסננים בשאילתה מניבים את הביצועים הכי טובים, לא תמיד כדאי או אפשר להוסיף מדד מורכב לכל שילוב של מסננים. צריך לאזן את האינדקסים המורכבים בהתאם לנקודות הבאות:
מגבלות על אינדקסים מורכבים:
הגבלה סכום המספר המקסימלי של אינדקסים מורכבים למסד נתונים -
200 אם לא הפעלתם חיוב בפרויקט Google Cloud .
אם אתם צריכים מכסה גדולה יותר, אתם צריכים להפעיל את החיוב בפרויקט. Google Cloud
-
1,000 כשמפעילים את החיוב בפרויקט Google Cloud .
אפשר לפנות לתמיכה כדי לבקש להגדיל את המכסה הזו.
הסכום המקסימלי של הגדלים של רשומות אינדקס מורכב של ישות 2 MiB הסכום המקסימלי של הערכים הבאים לישות: - מספר ערכי המאפיינים שנוספו לאינדקס
- מספר הרשומות באינדקס המורכב
20,000 -
- עלויות האחסון של כל אינדקס נוסף.
- השפעות על זמן האחזור של פעולות כתיבה.
בעיות בהוספה לאינדקס מתרחשות לעיתים קרובות בשדות עם כמה ערכים, כמו המאפיין tag של ישויות Photo.
לדוגמה, נניח שתכונת הסינון Photo צריכה לתמוך עכשיו בסעיפי סידור בסדר יורד שמבוססים על ארבעה מאפיינים נוספים:
| תמונה | ||
|---|---|---|
| מאפיין (property) | סוג הערך | תיאור |
date_added |
מספר שלם | תאריך/שעה |
rating |
Float | דירוג מצטבר של משתמשים |
comment_count |
מספר שלם | מספר התגובות |
download_count |
מספר שלם | מספר הורדות |
אם מתעלמים מהשדה tag, אפשר לבחור אינדקסים מורכבים שתואמים לכל שילוב של מסנני Photo:
Index(Photo, owner_id, -date_added) Index(Photo, owner_id, -comments) Index(Photo, size, -date_added) Index(Photo, size, -comments) ... Index(Photo, owner_id, size, -date_added) Index(Photo, owner_id, size, -comments) ... Index(Photo, owner_id, size, coloration, -date_added) Index(Photo, owner_id, size, coloration, -comments)
המספר הכולל של אינדקסים מורכבים הוא:
2^(number of filters) * (number of different orders) = 2 ^ 3 * 4 = 32 composite indexes
אם מנסים לתמוך בעד 3 מסננים tag, המספר הכולל של אינדקסים מורכבים הוא:
2 ^ (3 + 3 tag filters) * 4 = 256 indexes.
אינדקסים שכוללים מאפיינים מרובי-ערכים כמו tag מובילים גם לבעיות של אינדקס מתפוצץ שגורמות לעלייה בעלויות האחסון ולזמן אחזור ארוך יותר של פעולות כתיבה.
כדי לתמוך במסננים בשדה tag בתכונה הזו, אפשר להסתמך על אינדקסים שמוזגו כדי לצמצם את המספר הכולל של האינדקסים. הקבוצה הבאה של אינדקסים מורכבים היא המינימום שנדרש כדי לתמוך בתכונת הסינון Photo עם מיון:
Index(Photo, owner_id, -date_added) Index(Photo, owner_id, -rating) Index(Photo, owner_id, -comments) Index(Photo, owner_id, -downloads) Index(Photo, size, -date_added) Index(Photo, size, -rating) Index(Photo, size, -comments) Index(Photo, size, -downloads) ... Index(Photo, tag, -date_added) Index(Photo, tag, -rating) Index(Photo, tag, -comments) Index(Photo, tag, -downloads)
מספר האינדקסים המורכבים שהוגדרו הוא:
(number of filters + 1) * (number of orders) = 7 * 4 = 28
מיזוג האינדקסים מספק גם את היתרונות הבאים:
- מאפשר לישות
Photoלתמוך בעד 1,000 תגים ללא הגבלה על מספר המסנניםtagלכל שאילתה. - הפעולה הזו מקטינה את המספר הכולל של האינדקסים, וכך מקטינה את עלויות האחסון ואת זמן האחזור של הכתיבה.
בחירת אינדקסים לאפליקציה
יש שתי דרכים לבחור את האינדקסים האופטימליים למסד נתונים במצב Datastore:
שימוש במיזוג אינדקסים כדי לתמוך בשאילתות נוספות
- נדרשים פחות אינדקסים מורכבים
- הפחתת עלויות האחסון לכל ישות
- שיפור זמן האחזור של פעולות כתיבה
- מניעת אינדקסים מתרחבים
- הביצועים תלויים בצורת הנתונים
הגדרת אינדקס מורכב שתואם לכמה מסננים בשאילתה
- שיפור ביצועי השאילתות
- ביצועי שאילתות עקביים שלא תלויים בצורת הנתונים
- צריך להיות מתחת למגבלת האינדקסים המורכבים
- עלות אחסון מוגדלת לכל ישות
- זמן אחזור ארוך יותר של פעולות כתיבה
כשמנסים להבין מהם האינדקסים האופטימליים לאפליקציה, התשובה יכולה להשתנות בהתאם לשינויים בנתונים. דגימה של ביצועי שאילתות נותנת לכם מושג טוב לגבי השאילתות הנפוצות באפליקציה והשאילתות האיטיות שלה. המידע הזה יעזור לכם להוסיף אינדקסים כדי לשפר את הביצועים של שאילתות נפוצות ואיטיות.