גרסאות של אופטימיזציית שאילתות ב-Spanner

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

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

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

היסטוריית הגרסאות של הכלי לאופטימיזציה של שאילתות

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

גרסה 9: 21 ביולי 2026 (הגרסה העדכנית)

  • שיפור היעילות של הצטרפויות מסוג distributed apply (DA) על ידי שליחת העמודות הנדרשות מהקלט לצד המיפוי של ההצטרפות.

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

    לדוגמה, מאפשר בחירה של האינדקס ב-Singers((LOWER(FirstName))) אם הוא קיים בשאילתה הבאה:

    GoogleSQL

    SELECT s.SingerId, s.FirstName, s.LastName
    FROM Singers s
    WHERE LOWER(s.FirstName) > 'k'
    LIMIT 10;
    

    PostgreSQL

    SELECT s.singerid, s.firstname, s.lastname
    FROM singers s
    WHERE LOWER(s.firstname) > 'k'
    LIMIT 10;
    
  • שיפור הביצועים של חיפוש באינדקסים משולבים באמצעות אצווה ומיון של מפתחות לחיפושים רציפים יעילים באחסון.

  • שיפורים קלים בהערכת העוצמה (cardinality).

  • אם אין LIMIT מעל הפעולה apply, המערכת תעדיף באופן היוריסטי תוכניות עם distributed apply על פני apply עם distributed union בצד המפה.

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

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

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

גרסה 8: 28 באוקטובר 2024 (ברירת מחדל)

  • סעיפי WITH נלקחים בחשבון כשבוחרים תוכנית שמבוססת על עלות.

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

  • שיפור JOIN שינוי הסדר.

  • שיפור הביצועים של שאילתות עם תנאי IN (...) גדולים.

  • שיפרנו את הביצועים של GROUP BY במקרים מסוימים.

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

גרסה 7: 22 במאי 2024

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

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

  • הוספנו תמיכה בבחירה של הצטרפויות גיבוב (hash joins) על סמך עלות.

גרסה 6: 11 בספטמבר 2023

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

  • שיפור ההערכה של עוצמת הקבוצה ומודל העלויות.

  • הופעלה אופטימיזציה מבוססת-עלות לשאילתות DML.

גרסה 5: 15 ביולי 2022

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

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

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

גרסה 4: 1 במרץ 2022

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

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

    רמז להצטרפות:

    GoogleSQL

    SELECT ...
    FROM (...)
    JOIN@{join_method=hash_join, hash_join_execution=one_pass} (...)
    

    PostgreSQL

    SELECT ...
    FROM (...)
    JOIN/*@ join_method=hash_join, hash_join_execution=one_pass */ (...)
    

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

    • מספר ההרצות בצד ימין של הצומת הצאצא של הגיבוב גדול יותר ממספר ההרצות באופרטור הגיבוב.
    • גם זמן האחזור של צאצא ימני של אופרטור ה-hash join גבוה.

    כברירת מחדל (hash_join_execution=multi_pass), אם קלט הצד של ה-build של ה-hash join גדול מדי ולא נכנס לזיכרון, הצד של ה-build מתפצל לכמה קבוצות, ויכול להיות שנסרוק את הצד של ה-probe כמה פעמים. במצב החדש (hash_join_execution=one_pass), אם קלט הצד של ה-build לא נכנס לזיכרון, ה-hash join יועבר לדיסק, ותמיד יסרוק את הצד של ה-probe רק פעם אחת.

  • שיפור בבחירת מספר המקשים שמשמשים להזזה.

גרסה 3: 1 באוגוסט 2021

  • נוסף אלגוריתם חדש לצירוף, merge join, שמופעל באמצעות ערך חדש של רמז לשאילתה JOIN METHOD.

    רמז להצהרה:

    GoogleSQL

    @{join_method=merge_join}
    SELECT ...
    

    PostgreSQL

    /*@ join_method=merge_join */
    SELECT ...
    

    רמז להצטרפות:

    GoogleSQL

    SELECT ...
    FROM (...)
    JOIN@{join_method=merge_join} (...)
    

    PostgreSQL

    SELECT ...
    FROM (...)
    JOIN/*@ join_method=merge_join */ (...)
    
  • נוסף אלגוריתם חדש לצירוף, push broadcast hash join, שמופעל באמצעות ערך חדש של רמז לשאילתה JOIN METHOD.

    רמז להצטרפות:

    GoogleSQL

    SELECT ...
    FROM (...)
    JOIN@{join_method=push_broadcast_hash_join} (...)
    

    PostgreSQL

    SELECT ...
    FROM (...)
    JOIN/*@ join_method=push_broadcast_hash_join} */ (...)
    
  • הוספנו את האופרטור distributed merge union, שמופעל כברירת מחדל כשזה רלוונטי. הפעולה הזו משפרת את הביצועים של השאילתות.

  • שיפור קל בביצועים של סריקה ב-GROUP BY כשאין צבירה MAX או MIN (או HAVING MAX/MAX) ברשימת SELECT. לפני השינוי הזה, Spanner טען את העמודה הנוספת שלא מקובצת גם אם היא לא נדרשה על ידי השאילתה.

    לדוגמה, נניח את הטבלה הבאה:

    GoogleSQL

    CREATE TABLE myTable(
      a INT64,
      b INT64,
      c INT64,
      d INT64)
    PRIMARY KEY (a, b, c);
    

    PostgreSQL

    CREATE TABLE myTable(
      a bigint,
      b bigint,
      c bigint,
      d bigint,
      PRIMARY KEY(a, b, c)
    );
    

    לפני השינוי הזה, השאילתה הבאה הייתה טוענת את העמודה c גם אם היא לא נדרשת על ידי השאילתה.

    SELECT a, b
    FROM myTable
    GROUP BY a, b
    
  • שיפור הביצועים של חלק מהשאילתות עם LIMIT כשיש אופרטור cross apply שהוצג על ידי joins והשאילתה מבקשת תוצאות ממוינות עם LIMIT. בעקבות השינוי הזה, האופטימיזציה מחילה את המיון עם ההגבלה בצד הקלט של cross apply קודם.

    דוגמה:

    GoogleSQL

    SELECT a2.*
    FROM Albums@{FORCE_INDEX=_BASE_TABLE} a1
    JOIN Albums@{FORCE_INDEX=_BASE_TABLE} a2 USING(SingerId)
    ORDER BY a1.AlbumId
    LIMIT 2;
    

    PostgreSQL

    SELECT a2.*
    FROM albums/*@ force_index=_base_table */ a1
    JOIN albums/*@ force_index=_base_table */ a2 USING(singerid)
    ORDER BY a1.albumid
    LIMIT 2;
    
  • השיפור בביצועי השאילתות מתבצע על ידי העברת יותר חישובים דרך JOIN.

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

    דוגמה:

    SELECT
      t.ConcertDate,
      (
        SELECT COUNT(*) FROM UNNEST(t.TicketPrices) p WHERE p > 10
      ) AS expensive_tickets,
      u.VenueName
    FROM Concerts t
    JOIN Venues u ON t.VenueId = u.VenueId
    ORDER BY expensive_tickets
    LIMIT 2;
    

גרסה 2: 1 במרץ 2020

  • הוספת אופטימיזציות לבחירת אינדקס.
  • שיפור הביצועים של פרדיקטים מסוג REGEXP_CONTAINS ו-LIKE בנסיבות מסוימות.
  • משפר את הביצועים של סריקה בGROUP BY במצבים מסוימים.

גרסה 1: 18 ביוני 2019

  • כולל הרבה אופטימיזציות מבוססות-כללים, כמו predicate pushdown, ‏ limit pushdown, ‏ redundant join ו-redundant expression removal.

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

המאמרים הבאים