פיצ’ר חדש: Sequence-ים ברמת ה-Session

יוצא לי לאחרונה לקרוא ולכתוב הרבה לאחרונה על הפיצ’רים החדשים של אורקל 12c. לפעמים אני קורא על משהו שלא מושך את תשומת הלב שלי מספיק כדי לכתוב על זה באופן ישיר, אבל אחרי כמה שבועות אני נשאל איך מיישמים פונקציונליות בדיוק כזו ואז אני פתאום נזכר בפיצ’ר (ומתבעס שהוא בגרסה הבאה)…

בדיוק הדבר הזה קרה לי השבוע.

אחד הפיצ’רים שרפרפתי עליהם ולא מצאתי אותם מספיק שימושיים כדי לכתוב עליהם היא העובדה שהחל מאורקל 12c אפשר ליצור sequence ברמה של ה-Session. על פניו, לא נשמע כל כך מלהיב ואפילו לא מאוד שימושי – הרי מה כבר אפשר לעשות עם sequence כזה?

מה זה sequence

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

כשאני מסביר בקורסים מה זה sequence אני בדרך כלל אומר ש-sequence זה כמו מר סופר מרחוב סומסום. אתה מבקש ממנו מספר, והוא נותן לך מספר (את המספר הבא nextval). אם אחרי ששאלת מה המספר אתה רוצה לדעת מה המספר האחרון שהוא נתן לך אתה יכול לבקש אותו (currval) ועדיין תקבל אותו. אם אתה רוצה את המספר הקודם – זה אין. הוא יודע לספור רק קדימה.

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

עוד כמה דברים על :

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

הבעיה

הבעיה שעמדה בפני היא הבעיה הזו: יש לנו מערכת שיש לה הרבה מקורות מידע מקביליים. כל מקור מידע הוא Session שמתחבר, עושה מה שעושה ואז מתנתק. הרשומות שה-session צריכות ספרור רץ משלהן (הרשומה הראשונה – 1, הרשומה השנייה – 2 וכן הלאה) מכוון שהרשומות מייצגות שלבי ביניים בתהליך.

עד היום, כל ה-session-ים היו לוקחים את הספרור שלהם מ-sequence אחד, מקבלות מספרים לא רציפים ואסטרונומיים (ה-sequence כבר התחיל להחזיר מספרים של 8 ספרות). כשאנחנו היינו רוצים למצוא את כל הרשומות שמייצגות את השלב הראשון בתהליך, היינו צריכים להשתמש בפונקציה האנליטית row_number כדי למספר את הרשומות ולהוציא רק את אלה שהן השלב הראשון (או כל מספר אחר בשלבים). מבחינת שליפה זה נראה בערך ככה:

Select proc_id, step_id, value
  From (select proc_id,
               step_id,
               value,
               row_number over(partitionby proc_id orderby step_id) r
          From t_proc_steps)
 Where r = 1;
 

לא משהו – במיוחד אם מבינים שבטבלה שלנו יש המון רשומות ואנחנו היינו רוצים שיהיה אינדקס על העמודה של ה-step_id.

מה שאני נשאלתי זה האם יש אפשרות שבכל פעם שאנחנו מתחילים תהליך (session) המספור יתחיל מהתחלה ואז בתוך t_proc_step יהיה proc_id שזה מספר ה-session ו-step_id מ-1 עד כמה שיש שלבים בתהליך.

Sequence ברמת ה-Session

עד אורקל 12c אני לא מכיר פתרון שמאפשר את הדבר הזה. החל מאורקל 12אנחנו יכולים להגדיר שיהיה לנו sequence ברמה של ה-session:

CREATE SEQUENCE seq_step_session
   START WITH   1
   INCREMENT BY 1
   SESSION
/   

עכשיו הכול יותר פשוט: כל Session מתייחס ל-sequence כאילו הוא המשתמש היחידי שלו ומקבל ממנו מספרים רצים שמתחילים תמיד ב-1.

עוד שימושים שניתן לעשות בדבר הזה הוא כל מה שקשור בבניית נתונים בטבלאות זמניות. לדוגמה, אם ה-GTT שלנו הוא ON COMMIT PRESERVE ROWS אז סיום ה-session ינקה הן את הטבלה הזמנית והן את ה-sequence שבו היא משתמשת.

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

1 תגובה
  1. Oren Nakdimon
    Oren Nakdimon says:

    הי זהר.
    לפני גרסה 12 אפשר לנצל את העובדה שאורך החיים (כברירת מחדל) של משתנים גלובליים ברמת מארזים הוא כאורך חיי ה-Session.
    הנה דוגמה בסיסית לפתרון. הפירמוט משמאל מימין באחריותך 🙂

    CREATE OR REPLACE PACKAGE session_level_sequence AS
    FUNCTION next_val RETURN BINARY_INTEGER;
    END session_level_sequence;
    /

    CREATE OR REPLACE PACKAGE BODY session_level_sequence AS
    g_sequence BINARY_INTEGER := 0;
    FUNCTION next_val RETURN BINARY_INTEGER IS
    BEGIN
    g_sequence := g_sequence + 1;
    RETURN g_sequence;
    END next_val;

    END session_level_sequence;
    /

    ועכשיו אפשר פשוט לקרוא ל-session_level_sequence.next_val כדי לקבל את המספר הבא.
    אורן.

    הגב

השאירו תגובה

Want to join the discussion?
Feel free to contribute!

השאר תגובה

This site uses Akismet to reduce spam. Learn how your comment data is processed.