חומרי עזר לביצוע שאילתות

בדף הזה מוסבר הפלט של שאילתה שהופעלה באמצעות Query Explain. במאמר ניתוח של ביצוע שאילתות באמצעות Query Explain מוסבר איך להריץ שאילתה באמצעות Query Explain.

מושגים נפוצים

המושגים והמונחים הנפוצים הבאים מופיעים לאורך עץ הביצוע.

שורות ורשומות

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

משתנים

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

המשתנים הפנימיים הבאים יכולים להופיע בצמתי ההפעלה:

  • $__key__– המפתח הוא מזהה פנימי של מסמך. זהו מזהה ייחודי מוחלט עם הפרויקט, מסד הנתונים והנתיב המלא של המסמך.
  • $__id__-המזהה הוא מזהה ייחודי של מסמך בתוך האוסף שלו. הערך הזה ייחודי במסגרת אוסף יחיד.

לדוגמה, נניח שמשתמשים בצומת Compute כדי לחשב את __id__ מהמסמך __key__:

Compute
    |  $__id__1: _id($__key__)
    |  records returned: 1

מגבלות וטווחים

חלק מצמתי הסריקה משתמשים במאפיינים constraints ו-ranges כדי לתאר את טווח הערכים שנסרקים. המאפיינים האלה משתמשים בפורמט של עץ טווח שמכיל רשימת ערכים. הערכים האלה תואמים לרשימה המסודרת של המפתחות שמופיעים בהגדרת האינדקס. לדוגמה, הטווח הראשון שמופיע בעץ, כאן (1..5], תואם למגבלות של המפתח הראשון, כאן a, ברשימה המסודרת של המפתחות:

| index: type=CollectionGroupIndex, id=CICAgOjXh#EK, keys=[a ASC, b ASC, __key__ ASC]
| constraints: /
               |----(1..5]
                    |----[1L]

כל רמת הזחה מציינת את האילוץ שחל על המפתח הבא ברשימה. סוגריים מרובעים מייצגים טווח כולל, וסוגריים מעוגלים מייצגים טווח לא כולל. במקרה כזה, האילוץ מתורגם ל-1 < "a" <= 5 ול-"b" = 1.

בדוגמה הבאה עם כמה ענפים של a, האילוץ מתאים ל-1 < a <= 5 OR a = 10:

| constraints: /
               |----(1L, 5L]
               |----[10L]

משתנים מרכזיים

בחלק מצמתי הסריקה (כמו SequentialScan), יש גם רשימה של מפתחות כחלק מהמאפיין index, וגם מאפיין keys נפרד בצומת Scan. המאפיין keys בצומת Scan מציין את שם המשתנה של כל מפתח בהגדרת האינדקס, לפי הסדר. אפשר להשתמש במשתנים כדי להפנות לערכי זמן הריצה של השדה שנסרק בהמשך עץ הביצוע.

בדוגמה הבאה, הערך של השדה user במסמך הנוכחי ממופה למשתנה $user_1, והערך של date_placed ממופה ל-$date_placed_1.

index: type=CollectionGroupIndex, id=CICAgOjXh4EK, keys=[user ASC, date_placed ASC, __key__ ASC]
keys: [user ASC, date_placed ASC, __key__ ASC]

צמתי ביצוע

עץ של ביצוע שאילתה יכול להכיל את הצמתים הבאים.

SeekingScan

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

לדוגמה, שאילתה שבה a קיים ו-b שווה ל-1, שפועלת על אינדקס של ["a" ASC, "b" ASC], תצטרך לסרוק ולהחזיר טווח נפרד, שאולי לא יהיה רציף, לכל ערך נפרד של a. הגישה הזו יעילה יותר מחיפוש מלא של TableScan, אבל פחות יעילה מחיפוש יחיד של SequentialScan באינדקס מורכב של ["b" ASC, "a" ASC].

• SeekingScan
| constraints: /
               |----(-∞..+∞)
                    |----[1L]
| index: type=CollectionGroupIndex, id=CAE, keys=[user ASC, quantity ASC, __key__ ASC]
| keys: [user ASC, quantity ASC, __key__ ASC]
| properties: Selection { user }
| records returned: 1
| records scanned: 1

SequentialScan

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

key ordering length מתייחס למספר המפתחות שצריך לשמור ולהחזיר לפי הסדר המקורי שלהם. בסכימה של [k1, k2, k3], אורך של 0 בסדר המפתחות אומר שהסריקה יכולה להחזיר את התוצאות בכל סדר, אורך של 1 אומר שהתוצאות יוחזרו לפי סדר k1, אבל שורות עם אותו ערך k1 יכולות להופיע בכל סדר, ואורך של 3 מחזיר מסמכים בסדר ממוין מדויק.

• SequentialScan
| index: type=CollectionGroupIndex, id=CAE, keys=[user ASC, date_placed ASC, __key__ ASC]
| key ordering length: 3
| keys: [user ASC, date_placed ASC, __key__ ASC]
| limit: 10
| properties: Selection { a }
| ranges: /
| records returned: 1
| records scanned: 1

UniqueScan

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

• UniqueScan
| index: type=CollectionGroupIndex, id=CAE, keys=[user ASC, date_placed ASC, __key__ ASC]
| keys: [user ASC, date_placed ASC, __key__ ASC]
| properties: Selection { a }
| ranges: /
          |----(-∞..+∞)
| records returned: 1
| records scanned: 1

TableAccess

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

• TableAccess
|  order: PRESERVE_INPUT_ORDER
|  peak memory usage: 4.00 KiB (4,096 B)
|  properties: *
|  records returned: 1

LookupById

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

• LookupById
|  local_field: $localField_1
|  foreign_datasource: (default)#/**/foreign
|  output: $output_1

TableScan

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

הערך של order יכול להיות STABLE או UNDEFINED, כאשר STABLE מציין סדר דטרמיניסטי.

• TableScan
|  order: STABLE
|  properties: *
|  records returned: 1
|  records scanned: 1
|  source: (default)#/**/collection

HashAggregate

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

• HashAggregate
|  aggregations: [sum($b_1) AS total]
|  groups: [$a_1]
|  peak memory usage: 4.00 KiB (4,096 B)
|  records returned: 0

StreamAggregate

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

• StreamAggregate
|  keys: [foo ASC, bar ASC]
|  properties: Selection { baz }
|  aggregations: [$sum($foo_1) AS baz]

MajorSort

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

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

• MajorSort
|  fields: [a ASC, b DESC]
|  limit: 10
|  peak memory usage: 4.00 KiB (4,096 B)
|  records returned: 1

Concat

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

• Concat
├── • TableAccess
...
├── • TableAccess

Compute

הפונקציה מחשבת קבוצה של ביטויים ומקצה את התוצאות לקבוצה של משתנים.

• Compute
|  $user_1: user
|  $full_name_1: str_concat($first_name_1, " ", $last_name_1)
|  $address_1: UNSET
|  records returned: 1

סינון

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

• Filter
|  expression: $eq(foo, "bar")
|  records returned: 1

ערכים

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

• Values
| expression: [{__key__=/col/1}, {__key__=/col/2}]

Unnest

הפונקציה מבטלת את הקינון של הערך שנוצר על ידי צומת הצאצא.

• Unnest
|  expression: foo AS unnested_foo

מגבלה

מגביל את מספר השורות שמוחזרות לצומת ההורה.

• Limit
|  limit: 10
|  records returned: 1

היסט

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

• Offset
|  offset: 10
|  records returned: 1