גם “Data Science בשקל” – יכול להיות שווה הרבה! (על Tableau)

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

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

למשל:

  • למצוא קשרים לא-צפויים בין נתונים, למשל: הידע שכרטיסי אשראי עם מאפיינים מסוימים אחראים לפי-19 הונאות משימוש בכרטיסים אחרים – הוא ידע שניתן להפוך אותו ליתרון עסקי.
  • היכולת לזהות שתקלה או מצב עומד להתרחש בעזרת סדרה של נתונים מקדימים.
  • היכולת לזהות שמקרה קצה מסוים לא מתרחש או כמעט ולא מתרחש – הוא הזדמנות לקחת החלטה במערכת ולא לתמוך במקרה הזה / לבצע אופטימיזציה עסקית או של ביצועי המערכת.
הדרך להשיג ידע שכזה היא לא קלה, ולרבות מההצלחות להשיג תובנה משמעותית – קודמים כמות ניסיונות כושלים.
בעקבות הטרנדים החמים היום של “Big Data” ושל “AI/ML” – מפתחים רבים מחליטים להשקיע ולהעשיר את הידע שלהם בכיוונים של Data Science.
לפעמים זה ידע תאורטי, לפעמים זו התנסות בסיסית ביצירת רשת ניורונים או Random forest.
בעזרת הטכנולוגיות הללו, נעשים בעולם דברים מדהימים – ואותם אנשי-תוכנה מקווים להגיע להישגים באזורים שלהם.
אני חושב שזו טעות טקטית נפוצה:

  • Data Science, בעיקרML ובמיוחד Deep Learning – הם תחומים עם עקומת למידה תלולה למדי, עדיין.
    • איש תוכנה יכול להשקיע עשרות ומאות שעות בלמידה ופיתוח skill – שעדיין יהיה בסיסי מאוד, יחסית למי שעוסק בתחום במשרה מלאה. לא יהיה לאיש התוכנה יתרון יחסי ברור מול איש-מקצוע ב Data Science, במיוחד לא כזה עם ניסיון לא-מבוטל.
    • אני מעריך שככל שהזמן יעבור – יהיה קל יותר ללמוד וליישם פתרונות Data Science, כך שייתכן ש 100 שעות למידה היום – יהפכו ל 20 שעות למידה בעוד 5 שנים. חלקים רבים מהידע שנלמד היום – יהפכו לכמעט-לא-חשובים, עבור מגוון נפוץ של יישומים / בעיות.
  • דווקא שיטות “פחות-מתוחכמות” של Data Science עשויות להניב לאיש התוכנה יתרון יחסי: שיטות כגון שאילתות SQL, סקריפטים שמעבדים ומנתחים נתונים, או כלי ויזואליזציה.
    • התחומים / שיטות הללו מפותחים כבר מאוד – קל ללמוד אותם מהר, ויש מגוון רחב מאוד של כלים ופרקטיקות שתומכים בהם.
    • יש כאן יתרון יחסי ברור של איש תוכנה המכיר את המערכת מקרוב:
      • הוא מבין את הנתונים (או לפחות חלקים מהם) – בצורה עמוקה.
      • נתון שאינו מכיר – הוא יכול למצוא את הקוד וללמוד בדיוק כיצד הוא מתנהג.
      • הוא יכול להוסיף נתונים ולטייב נתונים, ולהבין בצורה מהירה מה המורכבות של שיפור / טיוב נתונים שכאלו.
        • מה הבעיה ללכת לקוד ולבצע עוד כמה בדיקות / להזיז מקום את הקוד שאוסף נתונים – כך שיהיה מדויק יותר? – לאיש Data Science זוהי מלאכה קשה מאוד.
ארצה להציג דוגמה לשימוש בכלי Data Science “פשוט”, שאינו קשור ללמידת מכונה או “Big Data”. ספציפית, אסקור כלי בשם Tableau שאני משתמש בו לאחרונה.
Workbook לדוגמה מ Tableau Public
מקור: https://public.tableau.com/en-us/s/gallery/books-made-movies

למה טאבלו (Tableau)?

טוב, אז יש מגוון רחב של כלים לשליפה והצגת נתונים.
הכלי הבסיסי ביותר הוא client (למשל SequelPro או HeidiSql) – שאני מניח שכולנו עובדים איתו, מידי פעם.

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

אין תחליף לכלי להרצת SQL (או שפה אחרת של בסיס הנתונים) – אבל כאשר אנחנו רוצים לחזור לנתונים, או לשתף אותם – זה לא מספיק טוב.

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

כלים דיי ידועים הם MyDBR או Redash (הישראלי / של יוצא GetTaxi) – שהם טובים ופשוטים, וקל מאוד להתחיל לעבוד איתם בזמן קצר.

אני אכתוב על Tableau שהוא “כלי BI”, כלומר שהוא יקר יותר (תשלום ע”פ מספר משתמשים, 30-70 דולר בחודש למשתמש), וההטמעה שלו היא מורכבת יותר.

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

בחרתי לדבר דווקא על Tableau כי זה כלי שנבחר לעבודה במקום העבודה הנוכחי שלי. יש לנו גם Redash – אבל בטאבלו אפשר לעשות יותר.
יש עוד סדרה של כלים דומים ל Tableau, כמו MicroStrategy, Qlik, או SiSense (גם חברה ישראלית). הכלים הללו, כמובן, הם לא שקולים לגמרי – ולכל כלי יש את החוזקות היחסיות שלו.

עוד נקודה שכדאי לציין כבר עכשיו היא שאין כלי BI מושלם. קל לדמיין כלי אולטימטיבי – אבל קצת יותר קשה לפתח אחד (אני מניח). לכל כלי שאי-פעם נחשפתי אליו היו גם צדדים מוגבלים ומעצבנים.

לטאבלו יש כמה גרסאות, אך אני רוצה לציין את החשובות שבהן:

  • Tableau Desktop – אפליקציית Desktop לזריזות וגמישות מרביים. זה הרישיון היקר יותר.
  • Tableau Server – גרסה וובית ומצומצמת יותר של גרסת ה Desktop. השיתוף הוא קל יותר – והרישיון עולה כחצי מחיר. רישיון של Tableau Desktop כולל גם רישיון ל Tableau Server על מנת לשתף את המידע.
  • Tableau Public – גרסה חינמית של ה Desktop, שניתן להשתמש בה רק מול שרת ציבורי של טאבלו בו הנתונים יהיו נגישים לכל העולם, וכמות מוגבלת של נתונים (15 מיליון רשומות).

ב Tableau Public אתם יכולים להגביל את הגישה של משתמשים אחרים לנתונים / לקוד המקור (ה Workbook) – אם כי משתמשים רבים מתירים את ההורדה.

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

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

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

Undo הוא חברכם הטוב 

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

להבין את ההבדל בין Measures ל Dimension

זה קצת מבלבל בהתחלה:

  • Measure הוא נתון שאנו רוצים להציג אותו, או בד”כ – Aggregation שלו (כמו SUM, AVG, אחוזון מסוים, וכו’). מכירות, אחוז הצלחה, וזמן ריצה – הם measures קלאסיים.
  • Dimension הוא נתון שלפיו אנחנו רוצים לפלח את הנתונים ולהציג אותם כשורה / עמודה / אזור בגרף.
    למשל: תאריך (שנה / חודש / יום), מיקום גאוגרפי, קטגוריה, סטטוס (הצלחה / כישלון) וכו’ – הם dimension קלאסיים.
איך יודעים מה זה מה? – זה לא כ”כ חד משמעי.

טאבלו ינחש בצורה “תבונית” מה הוא מה – ויקטלג לכם אותם ב Data pane:
טאבלו יטעה מדי פעם – ויהיה עליכם לתקן אותו, ע”י פעולות ה”Convert to Measure” או “Convert to Dimension”.
Measures יהיו בד”כ מספרים – עליהם באמת אפשר לבצע Aggregations.
Dimension יהיו בד”כ מחרוזות ותאריכים.
אבל מה אם אני רוצה להשתמש בנתון מספרי טהור, כמו זמן ריצה – כ dimension? לדומה להציג תהליכים מהירים ואטיים בנפרד?
במקרה הזה עליכם ליצור Bins (בתפריט של פריט המידע: …create/bins), שהוא בעצם שדה חדש המקטלג טווחים של הנתון (הרציף, עם אינספור ערכים) שבחרתם.
בטאבלו, כחצי מהזמן שמשקיעים בויזואליזציה יהיה בארגון הנתונים בצורה שטאבלו ידע לעבוד איתם בצורה נכונה. זה תהליך של ניסוי-וטעיה, שמתרחש תוך כדי בניית הויזואליזציה.

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

להבין את ההבדל בין Columns, Rows, ל Marks

גם זה מאוד בסיסי, אם כי מעט מבלבל בהתחלה.

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

באופן הזה מאוד קל לחשוב על טורים ועמודות כמימדים שונים בהם אתם עושים חישוב – ו marks – כנתונים (measures) שאותם נרצה להציג:

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

הנה הוספתי לטבלה הנ”ל עוד שני מימדים נוספים:

ההפרדה בין עמודות ושורות היא פחות חשובה, ההפרדה החשובה היא בין מימדים ל Marks, שלרוב יהיו גם מימדים ו measures.

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

Customer הוא אחד ה Segments, ומתחתיו ניתן לראות את השנים.

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

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

הנה אותה הטבלה בדיוק, כאשר אני מציג כ 3 measures כ marks שונים:

  • סכום העסקאות – כגדול הסימון (עיגול).
  • מספר העסקאות – כטקסט (label). הביטוי CNTD הוא קיצור של Count Distinct.
  • אחוז הרווח – כצבע (gradient), כאשר כחול הוא רווח, וכתום הוא הפסד. כתום גדול = הפסד גדול!

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

עוד Marks שניתן להשתמש בהם הוא סוג הצורה (בשימוש ב Shapes) או tool-tip שמופיע ב popup כאשר מצביעים על האיבר.

Show Me הוא כלי חשוב – לא רק למתחילים!

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

בפינה הימנית עליונה נמצא כפתור Show Me – שעוזר לי לדעת למה אני זקוק.
עבור היסטוגרמה, אומרים לספק measure אחד (קל!) – ומודיעים לי שטאבלו ייצור bin field מתאים. יש גם אזהרה שלא כל measure יעבוד.

אני זורק את ה measure של Sales לאחד המימדים (עמודות או שורות – לא משנה) – טאבלו אוטומטית מנחש שאני רוצה לעשות לו aggregation של Sum.
אח”כ אני לוחץ ב Show Me על גרף ההיסטוגרמה – ומקבל את התוצאה הבאה:

הערה: שיניתי את השנתות של ציר ה Y ל logarithmic scale – אחרת היה קשה להבחין בערכים השונים.

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

מה הצבעים ירוק וכחול אומרים?

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

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

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

השתמשו ב Calculated Fields

אופן חשוב בו ניתן לעבד נתונים היא Calculated Fields.
שימוש פשוט הוא פעולה חשבונית כזו או אחרת (חיבור, חיסור, חילוק), אבל אפשר גם לפתור בעיות יותר משמעותיות בטאבלו בעזרת calculated fields.

למשל, הנה סקריפט פשוט שיוצר מימד חדש מכמה שדות (שמותיהם – בכתום):

היה לי קשה יותר לבנות את המימד הזה בדרך אחרת / SQL query.

לטאבלו יש רשימה של פונקציות זמינות, ותחביר שמזכיר כתיבת פונקציות ב SQL – בהם ניתן להשתמש ב calculated fields. שימו לב שחלק מהפונקציות זמין רק מול data sources ספציפיים כמו Hive או Google BigQuery (המספקים את הפונקציות בצורה טבעית)

עבור חישובים מורכבים יותר אפשר להשתמש בשפת R – שפת תכנות לכל דבר ועניין.
כדי לכתוב Calculated Fields בשפת R יש להתקין מנוע חישובי בשם RServe המריץ את R. טאבלו ישלח את הנתונים ל RServe – שיבצע את החישוב של השדה הנתון – ויחזיר את התוצאות.

SCRIPT_STR(`substr(.arg1, regexpr(” “, .arg1) -1 )`, ATTR([Business Name ]))

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

השתמשו ב Filters

בכל ויזואליזציה – ניתן “לגרור” שדות לאזור ה “filters” ולסנן לפי ערכים מסוימים של השדה הזה. זה שימוש אחד ויעיל ל Filters.

שימוש נוסף חשוב הוא ב Dashboards, כאשר אני מצרף כמה ויזואליזציות ובמקום אחד יכול לפלטר את כולם באותה הצורה. מה שנחמד שה Filters ב Dashboard מופיעים ב View Mode (אם לא סילקנו אותם משם) – וכך הקהל הרחב של המשתמשים יכול להשתמש בהם, מבלי להכנס לעומק ה Data Model.

הנה דוגמה של Dashboard פשוט שיצרתי מ-2 הויזואליזציות הנ”ל:

הוספתי Filter דרך אחד מהויזואליזציות (תפריט = חץ למטה/filters – מציג לי את כל המימדים / measures שבשימוש ולכן ניתן לפלטר לפיהם).

בשלב הבא, אני משייך את הפילטר (דרך התפריט שלו) – לכל הנתונים על ה Dashboard:

עכשיו אפשר לראות שצמצום השנים בעזרת הפילטר – משפיע על כל הנתונים ב Dashboard. איזה יופי!

סיכום

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

הוא כלי רב-עוצמה, אך לא מורכב כ”כ לשימוש.

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

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

שיהיה בהצלחה!

משינה אויסלערן – או בקיצור: Machine Learning

Machine Learning הוא תחום שאמנם קיים בערך משנות ה-60, אך שהתפתח בעיקר ב 10-15 השנים האחרונות.

מנקודת מבט אחת, Machine Learning (בקיצור: ML) הוא כלי שמאפשר לפתור בעיות תוכנה, שלא ניתן לפתור בדרך הרגילה – קרי: בעזרת משפטי if ולולאות for.
ארתור סמואל, החלוץ בתחום תיאר זאת כ “give computers the ability to learn without being explicitly programmed”.

כמובן שיש בשכבות הנמוכות של פתרונות ה ML הרבה משפטי if ולולאות for, אך ML מספק שיטה מתמטית/סטטיסטית המאפשרת לחשוב בפרדיגמה שונה של “תכנות” על הבעיות האלה.

מפתחים “רגילים” שלא מכירים את התחום נוטים להגיב ל ML בעיקר באחת מ-2 צורות:

  • התלהבות ושקיקה ללמוד את הנושא, מתוך אמונה ש”זה הדבר הבא שישנה את עולם התוכנה, והעולם בכלל”
  • זלזול והתייחסות לקהילת ה ML כ “קבוצה של אנשים מתנשאים ומרוכזים בעצמם, שהשפעתם שולית”.
האמת – היא כנראה איפשהו באמצע.
בפוסט הבא אנסה לתת סקירה לא משוחדת של עולם ה Machine Learning, ומשמעויותיו.

היכרות בסיסית עם ML

לא כל בעיה ניתן לפתור בעזרת ML – להיפך. הבעיות העיקריות שניתן לפתור בעזרת ML מחולקות לקטגוריות הבאות:

  • Regression – חיזוי של ערך, על בסיס נתונים. למשל: שערוך ערך של דירה על סמך הנתונים שלה (שטח, גיל, וכו’) או הערכה מה יהיה סכום העסקאות של לקוח בחודש הקרוב – על סמך עסקאות עבר, גיל, ומדדים של הרגלי קנייה.
  • Classification – סיווג של entities למספר סגור של קבוצות מוגדרות, למשל: שביעות רצון של לקוח (3 ערכים אפשריים: נאמן, רגיל, נוטה לעזוב), האם עסקה היא לגיטימית או הונאה (2 ערכים אפשריים), וכו’.
  • Clustering – גיבוש קבוצות של פריטים מסוימים. למשל: ברוסיה יש 10,500 ערים – צור קבוצות של ערים דומות (ע”פ סדרה של נתונים על הערים, קרי: מספר תושבים, הכנסה ממוצעת, שטח, שנות קיום, וכו’).
  • Recommender Systems – חיזוי פריטים דומים שמישהו עשוי להתעניין בהם, למשל: אם אהבת דיסק של כנסיית השכל – אולי תאהב את הדיסק החדש של שלמה ארצי (לא!!!!!!)
    • Collaborative Filtering – “מי שאהב X אהב גם Y” – המלצת תוכן או מוצר למשתמש, ע”פ סיווג של משתמשים “דומים”, ותיאור הפריטים שקבוצת ה”משתמשים הדומים” נוטה לאהוב.
מקור: https://dataaspirant.com

את עולם ה ML מחלקים בדרך ל-2 קטגוריות:

Supervised Learning

כאשר יש לנו מאגר של נתונים ותשובות (= target value), שהושגו בצורה כזו או אחרת (מדידה, עבודה של מומחים, וכו’) – ואנו רוצים שהמחשב ינסה לחקות את התשובות.

דוגמה קלאסית: שערוך ערך של דירה. גם אם יש לנו נתונים של אלפי דירות ומחיר מכירה של כל אחד מהן (אתר מדלן?!) – זו תהיה משימה כמעט בלתי אפשרית לכתוב קוד בעזרת if ו for שיבצע שיערוך של מחיר דירה, ובצורה טובה.

בעזרת ML אנו יכולים לפעול באופן הבא:

  • להשתמש ב Domain Knowledge (בקיצור DK) על מנת למצוא, או לפחות לנחש את ה features (תכונות) שמסבירות את מחיר הדירה. מיקום, ושטח במ”ר הם features חזקים מאוד, קומה וגיל הבנין הם features בינוניים וצבע הקירות או גודל המטבח יחסית לגודל חדר האמבטיה – הם features זניחים או אפילו מטעים.
  • בשלב הבא אנו נבחר אלגוריתם למידה (מתוך מבחר אלגוריתמים בתחום) ונפעיל אותו על 80% מהנתונים שלנו (למשל).
  • האלגוריתם ירכיב מודל חיזוי, ע”פ כל מיני שיטות מתמטיות / סטטיסטיות – שניתן להריץ: לשלוח לו פרטים של דירה – ולקבל תשובה = מחיר משוערך.
  • נשתמש ב 20% הנתונים הנותרים שלא השתמשנו בהם ללמידה – לצורך ביקורת: עד כמה טוב המודל שנוצר? מה התפלגות התשובות שלו?
  • כך אפשר לחזור כמה מחזורים עד שאנו מוצאים אלגוריתם ו tuning שמספקים תוצאות שאנו מרוצים מהן.
  • שלב זה יש לנו תוכנה שיכולה לשערך בדיוק כזה או אחר (בשאיפה: דיוק דיי טוב) את העלות הצפויה של דירה ע”פ נתונים גולמיים.
  • כמובן שניתן לשפר את המודל עם הכנסה של Domain Knowledge נוסף: למשל אנו יכולים להעריך שיש הבדל בהתנהגות בין המרכז לפריפריה. אולי הרכבה של 2 מודלים שונים: אחד למרכז ואחד לפריפריה – תשיג תוצאה טובה יותר.
    • יש עוד כלים רבים לשיפור מודל החיזוי – מדובר בד”כ בתהליך איטרטיבי ומשמעותי של שיפורים.
Unsupervised Learning

זוהי קטגוריה מעט שונה של ML בה יש לנו סט של נתונים, אך ללא תשובות (target value) – מהם אנו מנסים להפיק תובנות.
למשל: אנו מנסים לסווג מאמרים לקבוצות הגיוניות, מבלי שיש דוגמה לסיווג שכזה.

ניתן להשתמש ב features כמו אורך המאמר, מספר המלים שחוזר פעמים רבות יותר בכל מאמר, או המצאות / אי המצאות של מילות מפתח.

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

שתי הקטגוריות של ML, “למידה מפוקחת” ו”למידה לא מפוקחת” – מייצרות מודלים שאינם מושלמים:
בבעיות Binary Classification (כאשר התשובה היא X או Y) הצלחות של 80% ואפילו 70% נחשבות להצלחה.
להזכיר: בכזו בעיה נקודת האפס היא 50% – השקולה להטלת מטבע, או התפלגות ידועה אחרת (קרי: ההסתברות האפריורית של האירוע).

אחוזי ההצלחה וכיצד מודדים אותם – תלויים כמובן בבעיה. לפעמים ניתן להשקיע זמן רב בניסיונות ליצור מודל חיזוי של ML – ופשוט לא-להצליח / להצליח ברמה לא-מספקת לצורך העסקי.
“55% אחוז חיזוי במקום בו 50% הוא ההתפלגות הידועה” – עשויה להיות לצרכים מסוימים כישלון צורב, ולצרכים אחרים – תועלת שראוי להשתמש בה.

המוטיב המרכזי לשימוש ב ML הוא לפתור בעיות שאין לנו פתרון טוב יותר עבורן:

אם אנו רוצים לסווג את המאמרים בדוגמה הנ”ל לכמה קבוצות על פי אורך המאמר (משהו שקל מאוד לתוכנה אמפירית לעשות) – אין טעם להשתמש ב ML – פשוט כותבים קוד שיעשה זאת. זה יותר קצר, מהיר, ומדויק.

מצד שני, טכניקות של ML מסוגלות לפתור בעיות שלא היה ניתן לפתור בצורה אחרת: מזיהוי כתב יד, המלצות תוכן (“אנשים שקנו X גם קנו Y”), זיהוי פריצות אבטחה, או נהיגה של רכב אוטונומי. את כל הבעיות הללו – אתם מוזמנים לנסות ולפתור בעזרת קוד אימפרטיבי 🙂

תהליך העבודה (Workflow) של ML

תהליך העבודה של ML, הוא מעט יותר מורכב ממה שתיארתי. מכיוון שעיקר העבודה על ML היא התהליך ולא כתיבת קוד – אפרט מעט יותר על התהליך.
אני אתמקד בתהליך שמתאים ל Supervised Learning, כמו בעיית רגרסיה (ניבוי ערך של נכס נדל”ן).

השלבים בתהליך הם:

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

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

מי יכול לדעת ששישה חודשי עבודה על ניסיונות המלצה שונים הולכים לרדת לטמיון?
דרוש כאן בעיקר Domain Knowledge עמוק ואיכותי ו/או מתודולוגיה שתזהה כישלון בשלב מוקדם.

השגת הנתונים (Obtaining Data)
יש להשיג נתונים “מוצלחים”, ולא סתם נתונים “באיזור הבעיה”.
זה אומר הרבה פעמים להתחיל לאסוף נתונים שלא נאספו בעבר, ולהבין המשמעות המדויקת של כל נתון. לכמות הנתונים יש גם חשיבות גדולה: אלגוריתמים רבים יהיו מוצלחים הרבה יותר – כאשר יש להם יותר נתונים ללמוד מהם.

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

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

“.More data beats clever algorithms, but better data beats more data” — פיטר נורוויג (המחבר-שותף של הספר הנודע “AI: A Modern Approach” ומנהל מחקר בגוגל).

קרצוף הנתונים (Scrubbing Data)
גם ברגע שיש נתונים “נכונים “- לרוב יהיו להם בעיות איכות (Data Quality):

  • להשלים ערכים חסרים (או להסיר אותם, אם תיקון לא אפשרי). באג בפרודקשיין עשוי לגרור לאחוז כזה או אחר של נתונים שגויים או חסרים – לאורך תקופה.
  • לתקן אי התאמות. למשל שמי הופיע פעם בספריית הוידאו גם כ “ליאור בר און” וגם כ “ליאור בר-און” – הייתי מיוצג כשני אנשים, למרות שאני אדם אחד – מה שיגרום להטיה בניתוח הנתונים.
    • יש טכניקות שונות (חלקן מבוססות ML) בכדי להתאים ולזהות שבעצם מדובר באותו האדם (בסבירות כזו או אחרת)
  • נורמליזציה של הנתונים, למשל: כל התאריכים באותו ה format כך שניתן יהיה לעשות השוואות. המרה של מיילים לקילומטרים, סדר נתונים כזה לסדר אחר, וכו’. ישנו כלל של ML שטוען: “הנתונים שתקבלו תמיד יהיו בפורמט הלא-נכון”
שלב השגת הנתונים + “הקרצוף” נחשבים בד”כ לכ 50-80% מכלל העבודה ב ML Workflow – החלק הארי.
שלב זה דורש יכולות תכנות, קצת הבנה סטטיסטית (עבור תיקונים וקירובים), ומעט Domain Knowledge – על מנת להבין את הנתונים טוב יותר.
כמעט תמיד ניתן להשקיע עוד עבודה בכדי לשפר עוד יותר את איכות הנתונים – וחשוב לדעת גם מתי “לעצור”.
בחירת האלגוריתם
ישנם עשרות אלגוריתמים של ML, וכמה שרלוונטיים לכל סוג של בעיה. עליכם להבין את הנתונים ואת האלגוריתם – על מנת (לנסות ו)להתאים את האלגוריתם הטוב ביותר.
למשל: בעיה של Binary Classification ניתן לפתור בעזרת Naive Bayes (מודל סטטיסטי שלא דורש כמויות גדולות של נתונים ורץ מהר), בעזרת Logistic Regression (המבצע רגרסיה בין features ע”פ משקולות נתונות), או עץ החלטה (שמנסה לשערך הסתברות של כל feature בנפרד – ואז לסכם את סך ההסתברויות).

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

שלב זה הוא Pure Machine Learning Knowledge

בתרשים זה ניתן לראות כיצד בחירה של אלגוריתם משפיעה על אחוז הטעות של האלגוריתם. תמיד קיים tradeoff בין טעות מסוג I וטעות מסוג II, אבל ניתן לראות שאלגוריתם ה Random Forest עליון במקרה זה על האלגוריתמים האחרים. מקור: wise.io

אימון המודל

זהו השלב בו מזרימים את הנתונים לאלגוריתם, ובד”כ בונים תהליך אוטומטי שיעשה זאת.
נרצה לנסות אימון של המערכת עם קבוצות שונות של features וכך לבדוק אילו features הם מוצלחים יותר לפתרון הבעיה. זהו סוג של fine tuning של האלגוריתם, למשל: האם כדאי לשלוח median או average? אולי כדאי average כאשר מנקים מעט נקודות קיצון?
כיצד ניתן לצמצם את כמות ה features (קרי: סוגי הנתונים)? לרוב – פחות features יובילו לכמות קטנה יותר של טעויות.

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

שלב זה דורש הבנה סטטיסטית, מעט תכנות, ויכולות תפעול.
בחינת המודל
בשלב זה אנו מריצים את קבוצת הביקורת (או טכניקה אחרת שבחרנו) על מנת לבחון את הצלחת המודל.
זהו שלב בעיקר מדעי / סטטיסטי – בו אנו מנסים להעריך עד כמה המודל מוצלח.
השלב הבא הוא לא GA (כלומר: General Availability).
בד”כ יהיו השגות חדשות על איכות הנתונים / סוג הנתונים הנדרש / התאמת האלגוריתם וכו’.
מכאן חוזרים לכמה איטרציות נוספות של שיפורים – עד שמגיעים לרמה הרצויה.
כמה איטרציות? תלוי כמה טוב צריך להיות המודל, כמה זמן יש לכם, ועד כמה אתם מעריכים שזמן נוסף ישפר את המודל.בסופו של דבר, יש מודל חיזוי מספיק טוב – שניתן לחבר למערכות ה Production ולהתחיל להשתמש בו.

סיכום

עברנו בצורה זריזה על העולם של ה Machine Learning, וניסינו להפריך את הפנטזיה של “קוד שכותב את עצמו, בזמן שהמתכנת שותה קפה או משחק בפינג-פונג”.ML היא סוג של שיטה מדעית לחיזוי על סמך מציאת דפוסים (Patterns) בנתוני עבר. יש בה הרבה יותר מן האומנות (הרבה בחירות לא מדויקות וניחושים מושכלים, הרבה fine-tuning) – מאשר תחומים קלאסיים של כתיבת תוכנה.

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

התחום הזה הוא לא פשוט בכלל: זה לא כמו ללמוד עוד שפת תכנות או עוד Framework.
ספקי ענן כאלו אחרים יספרו לכם שיש להם “Machine Learning as a Service” ושהיום הכל יותר פשוט: לא צריך דוקטורט, אלא רק חשבון ב – ואפשר להתחיל להריץ ML.
זה נכון – התהליך הופך לנגיש יותר ויותר מבחינת התפעול, אך אין עדיין (למיטב ידיעתי) – התקדמות משמעותית בניסיון לייתר את המומחיות בתחום.

שיהיה בהצלחה!

לינקים רלוונטיים:

איך ללמוד ML בשנה: מאפס – לעבודה מעשית

הקורס של גוגל ל Deep Learning – ה “Docker” של עולם ה ML… – גם קורס זה בחינם.מי שמסיים בהצלחה אחד מהקורסים הנל – מוזמן לבוא ולכתוב פוסט אורח בנושא 🙂

https://charlesmartin14.wordpress.com – בלוג שמנסה להסביר לעומק קונספטים שונים ב ML

ביג דאטה: מחסני נתונים, אגמי נתונים, ומרכולי נתונים – סדר בבלאגן

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

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

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

כאשר אנו רוצים לבצע ניתוחים מקיפים על הנתונים במערכת האופרטיבית – יש בעיה אמיתית פשוט “להריץ שאילתות על בסיס הנתונים האופרטיבי”:

  • האינדקסים ומבני-הנתונים בבסיס הנתונים האופרטיבי מותאמים לשימושים האופרטיביים (למשל: הכנסה ועדכון של רשומות בתכיפות גבוהה), ופחות לצרכים האנליטיים (למשל: שאילתות גדולות עם הרבה joins). התוצאה: השאילתות יכולות לקחת זמן רב מאוד.
  • הפעלת שאילתות כבדות על בסיס-הנתונים האופרטיבי יכולות לפגוע בתפקוד השוטף. אמנם גם ניתוח נתונים הוא חשוב, אך הוא כמעט-תמיד פחות דחוף מהמשך הפעולה התקין של המערכת האופרטיבית.
Data Reservoir, השם הקודם (או הפחות נפוץ) של Data Lake. מקור: O’Reilly Radar.
יש הטוענים ש”מאגר נתונים” הוא מונח מדויק יותר, אך אין ספק ש “אגם נתונים” הוא המונח הפופולרי.

התמודדות עם בסיס נתונים אופרטיבי “גדול מדי”

מה עושים?

בתור שלב ראשון אפשר לייצר Replica של בסיס הנתונים האופרטיבי – ולהריץ עליה את השאילתות.
אבל:

  1. רפליקה משכפלת את מבני-הנתונים והאינדקסים מבסיס הנתונים האופרטיבי – שכבר ציינו שאינם אופטימליים לשאילתות האנליטיות.
  2. אם נעמיס את הרפליקה יותר מדי, אנו עלולים לגרום להאטה גם בבסיס הנתונים הראשי – שעסוק בלהמתין לרפליקה שתקבל את העדכונים שלו.

השלב הבא בהתפתחות הוא ליצור מחסן נתונים (Data Warehouse, או בקיצור DWH או DW) – בסיס נתונים בו מאוחסן עותק של הנתונים מבסיס הנתונים האופרטיבי (ייתכן שב delay מסוים, נאמר שעה עד יממה) – אבל עם החופש ליצור סכמה שונה, ואינדקסים שונים.

מקור: הבלוג של James Serra
ה ETL (קיצור של Extract, Transform, and Load) הוא התהליך ששלוף נתונים מבסיס הנתונים האופרטיבי, ממיר אותם לסכמה של בסיס הנתונים האנליטי וטוען אותם לשם.

כעת אנו יכולים לבצע שאילתות אנליטיות “כבדות” על ה DWH. הן:

  • ירוצו מהר יותר – כי מבנה הנתונים / האינדקסים מותאמים לשאילתות.
  • לא ישפיעו על הביצועים או ה Stability של בסיס הנתונים האופרטיבי (!Hurray)
בנוסף ב DWH מקובל:
  • לשמור נתונים לטווח ארוך – וכך לשחרר את המערכת התפעולית מלאחסן אותם.
    נאמר: ה DWH יכיל נתונים עשר שנים אחורה, בעוד בסיס הנתונים האופרטיבי – נתונים של חצי שנה אחרונה בלבד.
  • עבור הנתונים שיש הרבה מהם – שומרים לרוב סיכומים, ולא את כל הנתונים המקוריים שהיו במערכת התפעולית.
    למשל: במקום סכום של כל עסקה – שומרים רק את סכום העסקאות היומי, מה שיכול לצמצם את כמות הנתונים בסדרי-גודל, ובהתאמה להקל על השאילתות האנליטיות (שרצות עכשיו על פחות נתונים).
    יש לזה מחיר: אנו מאבדים נתונים – היכולת להבין את הפיזור המדויק של סכומי העסקאות, למשל.
  • להשתמש במהדורה מעט שונה של Database Server שמתאימה בצורה טובה יותר לצרכים אנליטיים. למשל: Vertica, Greenplum, Sybase IQ – הם בסיסי נתונים שמיועדים לשמש כ DWH.

מהפיכת הביג דאטה

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

הגידול בכמות הנתונים לחץ על מערכי ה DWH הקיימים, וטכנולוגיות ה NoSQL/BigData החדשות – יצרו הזדמנות לשינוי.

מקור: הבלוג של James Serra

ה DWH היה בשלב זה כבר פתרון מקובל, אך היו לחצים שהלכו וגברו:

  • חלק מהנתונים החלו לנהל בבסיסי נתונים לא-רלציונים – שלא נתמכים / נתמכים בצורה חלקית ע”י כלי ה ETL המסורתיים. מצבים של אי-עקביות בנתונים (inconsistency) וסכמה דינמית (למשל ב Document Databases) הפכו את מלאכת ה ETL ל”גיהינום” עבור ה DBAs.
  • כמות הנתונים במערכת האופרטיבית גדלו בצורה דרמטית – מה שגם הקשה על ה ETL להתבצע בזמנים טובים ו / או להישאר מעודכן לכל סוגי הנתונים שנוספו.
  • ברגע שה DWH לא מעודכן בכל הנתונים האחרונים, מערכות ה BI הן כבר פחות טובות – והמשתמשים הזקוקים לנתונים מתחילים למצוא “דרכי-מעקף” על מנת להשיג ולנתח את הנתונים שלהם.
בעזרת אכסון “אינסופי” וזול – נוצר מודל חדש לאיסוף וניתוח נתונים: אגם הנתונים (Data Lake):
  • כל המידע נאסף, בצורה גולמית וללא עיבוד (“as-is”), מהמערכות התפעוליות – ונשמר על גבי שטח האכסון האינסופי (Hadoop, S3, או Azure Data Lake).
    • נתונים שהמערכת התפעולית לא יכולה להמשיך ולשמור (משיקולי ביצועים) – נשמרים ולא נזרקים.
    • נגמר המירוץ של ה DBAs לעקוב ולהתאים את ה ETL לשינויי הסכמה במערכת התפעולית. המנגנון החדש יודע לאסוף את כל הנתונים.
  • מאוחר יותר, כשיהיה צורך מעשי בנתונים – ינקו אותם, יסכמו אותם, וינתחו אותם, באותו הרגע.
    • ה Stack של Hadoop – נבנה ממש לצרכים שכאלו.
תהליך העברת הנתונים ל Data Lake נקרא ELT (קיצור של Extract, Load…. ואז Transform), כאשר שלב ה Transform הוא לרוב ארגון מאוד בסיסי של הנתונים, כמו סידור שלהם בתיקיות / המרת פורמט הקבצים לכאלו שקל יותר לסרוק.
ב Hadoop למשל, נהוג להמיר את הנתונים (שמגיעים לרוב כהרבה קבצי JSON או CSV) לאחד מהפורמטים הבאים:
  • Avro – פורמט כללי, שדוחס את הנתונים ומאפשר לחלק קובץ ל-2 מבלי לקרוא את כולו (כי הנתונים שמורים במבנה ידוע). זו תכונה חשובה ל Map-Reduce.
  • Parquet – פורמט ששומר את הנתונים בצורה Columnar ומאפשר לקרוא מהדיסק את עמודות ספציפיות של הנתונים. הדחיסה כאן היא אפילו גבוהה יותר, כי הדמיון בין ערכים באותה עמודה – הוא באופן טבעי גבוה יותר.
המוטיבציה לדחוס את הנתונים היא: א. עלות אכסון  ב. צמצום זמן ה I/O שנדרש לטעון את הנתונים לזיכרון.
Hadoop, למשל, לא מתנהג יפה עם הרבה קבצים קטנים – ולכן יש להכין לו קבצים גדולים יותר, המסכמים “אצווה של רשמות”.
תהליך ELT. מקור: www.ironsidegroup.com
ה Data Lake הוא בעצם גישה הפוכה לגישת ה DWH:
  • מהגישה החרוצה: ניקוי, ארגון, וסיכום הנתונים ואז שמירה שלהם מה DWH – המאפשרת שליפה קלה.
  • לגישה העצלה: שמירת כל הנתונים המלוכלכים, raw, עם כפילויות וחוסרי התאמות ב Data Lake. ניקוי וסידור הנתונים יתבצע – רק ברגע שרוצים לתשאל אותם.
מקור: Martin Fowler
מי שבקיא ברזי ה Agile יודע בוודאי שדחיינות ועצלות הם Best Practices. זה כנראה נשמע רעיון טוב לאמץ את הרעיונות החשובים הללו בעולם הנתונים.
מי שהלך רחוק עם רעיונות ה laziness ב Data Lake שלו, עלול לגלות שהוא יצר לעצמו ביצת הנתונים (Data Swamp): מצב בו הנתונים ב Data Lake כ”כ מבולגנים ו”מלוכלכים” – שהערך מניתוחם לא מצדיק את העלות הגדולה בניקוי והסידור שלהם בדיעבד. הנתונים הם שם, שמורים ב Data Lake – אבל בעצם לא משתלם להתחיל ולהתעסק איתם (במקרים מסוימים – כמובן).
סידור נתונים בשלב מוקדם הוא לעתים רבות זול ופשוט הרבה יותר מסידור שלהם בדיעבד. למשל:
  • הסכמה וצורת שמירת הנתונים השתנו עשרות פעמים בתקופה – ואין לנו דרך לדעת בדיוק ממתי השינוי. שמירת שדה “version” על הנתונים במקור – היה יכול להיות השקעה קטנה שתחסוך זמן רב בעתיד.
  • נתונים שחסר איזה מפתח או נתון לקשר ביניהם. אם היינו מוסיפים זאת במקור – זו הייתה תוספת קטנה מאוד, אבל כיום צריך להתחיל להריץ יוריסטיקות וניתוחים – רק על מנת לקשר את הנתונים שהיו עד לא מזמן “במרחק נגיעה”.
  • שמירת נתונים בצורה אחידה, למשל שמירת תאריכים בפורמט אחיד (האם 1/4/12 זה אפריל או ינואר?) – או הקפדה על שמירת ה timezone הרלוונטי. נתונים שלא נשמרו כך – בדיעבד קשה לנקות ולסדר.
  • שמירת פרטים על המערכת ממנה מגיעים כל מקבץ-נתונים – יכול לסייע מאוחר יותר לקבוע את האיכות שלהם, או לשפר אותה.
  • לאסוף “חוסרי-נתונים”. יש סיפור על חברת טלקום שבנתה מערך Big-Data מרשים, אבל שכחה לאסוף אינדיקטור על ניתוק שיחה (שלא נשמר בבסיס הנתונים האופרטיבי – אני מניח). אחרי שנה+ של צבירת נתונים, היא לא הייתה מסוגלת לנתח בעיות במערכת – כי היה לה רק “מידע חיובי”.
    נקודה זו מתייחסת גם לנתונים שהמערכת האופרטיבית “תיקנה”, למשל – כאשר היא קובעת “ערך מקסימום” לסוג נתון כלשהו, עדיין עשוי להיות מעניין מה היה הערך המקורי.
  • כדאי לעקוב ולתעד את השמירה של מידע רגיש (מספרי טלפון של משתמשים, למשל) – כדי שיהיה ניתן להגן עליו. לא כל אנליסט עסקי אמור להיות מסוגל לגשת לנתונים הללו.
הנה דוגמה לארגון מקובל של נתונים בתוך ה Data Lake:

ה RAW הם נתונים שהגיעו מהמערכות התפעוליות ללא כל עיבוד, כאשר ה Gold הוא storage של הנתונים לאחר עיבוד מסוים. ה Work הוא אזור העבודה של ה Data Scientists, ויש אזור Sensitive אליו מעבירים את כל הנתונים הרגישים (שמחליטים לשמור. לפעמים פשוט מטשטשים אותם).

נוטים לרוב להבחין בין אנשי BI / Data Analysts שעובדים מול נתונים נקיים יחסית (“Gold”) ל Data Scientist – שמבינים טוב יותר את הבעיות השונות של נתונים (חוסר עקביות, פורמטים לא-אחידים, סתירות), ויכולים אף לכתוב custom code בכדי “לנקות נתונים קשים”.

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

חלוקת הנתונים בארגון

כמו תמיד, הארכיטקטורה הנקייה, בה יש DWH אחד ו Data Lake אחד ממנו כל הארגון צורך נתונים, היא טובה – בעיקר כתיאוריה.

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

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

בסה”כ זה סיפור קלאסי של trade-offs כאשר ליחידות ארגוניות שונות, מתאימים trade-offs שונים ברמת הנתונים.
לעתים אלו יחידות עסקיות שונות (כספים, מכירות, שירות), לעתים זו רמת-פירוט (הנהלה בכירה, תפעול בשטח) ולעתים חלוקה אחרת (למשל: התפעול של ארה”ב מול התפעול של אירופה).

מקור: datamartist.com

מתוך כך צצו, עוד בימי ה DWH – “מרכולי הנתונים” (Data Marts), שהם סוג של DWH קטן וממוקד.

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

ישנן עוד כמה שאלות הנוגעות לקשר בין ה DWH ל Data Marts. למשל: האם קודם יוצרים את ה DWH ואז גוזרים ממנו Data Marts, או האם נותנים ליחידות Data Marts ואז אוספים אותם ליצירת DWH ארגוני? אם ישנם נתונם שנכונים ל-2 Data Marts, האם להחזיק אותם ב Data Mart שלישי או ב DWH? וכו’…

מקור: datamartist.com
באופן דומה ל DWH, גם ב Data Lake צפוי שיהיו אזורים מיועדים ליחידות / רמות עסקיות שונות. כל אחד – והצרכים הייחודיים שלו. מרטין פאוולר, למשל, קרא להם “Lakeshore Data Marts”.
מה ההבדל בין Data Mart ל “Data Silos” – מאגרי מידע שיחידות בארגון שומרות לעצמן ולא משתפות עם אחרים?
אני מניח שאלו הבדלים של נקודות מבט: החצי המלא והחצי הריק של אותה הכוס.

סיכום

כמה Best-practices שכדאי לשקול בעבודת ארגון הנתונים:
איסוף וארגון נתונים:
  • להשתדל לאסוף ל Data Lake נתונים ברזולוציה של אירועים בעלי משמעות עסקית (קנייה, הצעת מחיר, רישום, וכו’).
    • זו הרזולוציה שלרוב יהיה מעניין לנתח.
  • לשלוח את הנתונים ל Data Lake לא כשהם ממש Raw, אלא לאחר עיבוד-קל (“Medium-Rare”):
    • להשתדל “לשטח” לתוך האירוע נתונים חשובים שיהיה קשה לקשר אותם מאוחר יותר. למשל: באירוע הצימוד בין נהג ונוסע, מעניין לשמור את המיקומים המדויקים שלהם באותו הרגע, כפי שהם ידועים לשרת. חלק הקוד שמפיק את אירוע-הנתונים יכול לספק נתון כזה בקלות יחסית, אבל להגיע לתובנות כאלו בדיעבד – זה יכול להיות קשה, ואפילו לא מדויק. הבנה עמוקה של הביזנס – היא כמובן המפתח להחלטה.
    • להוסיף metadata שבסבירות גבוה יכול להיות שימושי בעתיד: גרסה של מבנה הנתונים, מה לא נשמר ומאיזו סיבה, ציון תיקונים שנעשו בנתונים או ציון נתונים רגישים, וכו’
  • להחליט ע”פ הצורך אילו נתונים רוצים להכין / “לנקות” ב Data Lake בצורה יזומה (“Golden Data” או “tidy data”) – כדי שיהיו זמינים לניתוח מהיר. אלו לרוב הנתונים שמתארים את המדדים הביצועיים החשובים של הארגון.
  • לנסות ליצור סדר מובן ב Data Lake, ולא להפוך אותו ל Data Swamp. איזה סדר? מה שמתאים לצרכים הייחודיים של הארגון שלכם.
    • אנשים בתחום מדברים על תכון ה data pipeline (תהליך ניהול הנתונים) ו / או ה data lineage (המסלול והתחנות בו עוברים הנתונים לאורך חייהם).
  • (שנוי במחלוקת): נסו להוסיף נתונים ל Data Lake ב Pull (כלומר: ע”פ צורך ניתוח ממשי), ולא ב Push (כלומר: כי הם שם).
    • היתרון: יהיה לכם הרבה פחות “זבל” ו”בלאגן” ב Data Lake.
    • החיסרון: לא תוכלו לחקור נתונים שלא שמרתם.
שימוש בכלים:
  • “לשחק” בציר היכולות (ה trade-offs) בין Data Warehouse ובין Data Lake.
  • “לשחק” בציר היכולות בין ארגון מידע ריכוזי (DWH או Data Lake מרכזי) לארגון מידע מבוזר ע”פ צרכים (Data Marts או אזורים ספציפיים ב Data Lake).
בסופו של דבר, אלו הם כלים: הם לא “טובים” או “לא-טובים”. הם פשוט שימושיים – למקרים וצרכים מסוימים.

שיהיה בהצלחה!

—-
לינקים רלוונטיים
מרטין פאוולר על אגמי נתונים – http://martinfowler.com/bliki/DataLake.html

מערכות מבוזרות – מבט עדכני

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

קיטרתי – גם אני לא עשיתי זאת בעצמי (כמעט).

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

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

  • מוצרים: אפליקציית לקוח של טורנט, Tor (רשת פרוקסי לאנונימיות), או משחק Massively Multi-player Online.
  • Frameworks: המאפשרים פתרון בעיות מבוזרות ב”רמת הפשטה גבוהה”.
יש משהו מאוד קוסם בסקירה כיצד מוצרים מבוזרים עובדים – זה יכול להיות ממש מעניין!
האמת היא שיש לי (ובכלל בקהילה) – ידע מוגבל על הנושא. (הנה פוסט נחמד על Tor)
 
בסקירה של קטגורית Frameworks יש משהו יותר מעשי: סביר יותר שתבחרו Framework לעבוד בו – מאשר לכתוב מערת מבוזרת מ scratch, תוך כדי שאתם מושפעים ממימוש של מערכות אחרות.
כמו כן – הידע עליהן זמין ונגיש. לאחרונה התחלנו לעבוד עם Hadoop – מה שעוזרת לי לשלב את תוכן הפוסט עם העבודה השוטפת.
 
בסופו של דבר, גם ה Frameworks וגם המוצרים המבוזרים שמתוארים בפוסט עושים שימוש נרחב במנגנונים (“פרימיטיביים”) של מערכות מבוזרות שתיארתי בפוסט הקודם: Multi-cast ורפליקציה, בחירת מנהיג, השגת קונצנזוס ועוד. חלק מכובד מהמערכות שאתאר בפוסט זה משתמש ב Zookeeper, מוצר שהזכרתי בפוסט הקודם – בכדי לבצע את הפרימיטיביים המבוזרים הללו.
 
 
תוך כדי כתיבת הפוסט – נוכחתי שאני מתמקד בקטגוריה מאוד ספציפית של מוצרים מבוזרים: מוצרי Big Data.
 
זה בסדר.
 
מוצרי Big Data לרוב מחשבים… הרבה נתונים. כ”כ הרבה נתונים שלא ניתן לאחסן במחשב אחד. לרוב גם לא בעשרה.
כדי לטפל בכמויות הנתונים (Volume) או במהירות שלהם (Velocity) – זקוקים למערכת מבוזרת. אותם מוצרים (או Frameworks) הם גם במובן אחד “מערכת מבוזרת”, וגם “מוצר Big Data”. בפוסט – נבחן בעיקר את הפן המבוזר שלהן.
 
בכל מקרה: כנראה שחלק מכובד מאוד מאנשי התוכנה שמתמודדים עם מערכות מבוזרות – עושים זאת דרך עבודה עם מוצרי Big Data, הפופולריים כ”כ היום.
 
 
בקיצור: זהו איננו פוסט על Big Data. יום אחד אולי אקדיש לנושא פוסט ראוי, ואולי גם לא 🙂
 
 

חישוב מבוזר

Scatter – Gather הוא השם המקובל לדפוס חישוב מבוזר, המבוסס על 2 רעיונות:

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

נ.ב. “זמן סביר” הוא יחסי. לא נדיר להיתקל בשאילתות שרצות על מערכות Hadoop במשך שבועות – עד לסיום החישוב.

Map Reduce – הוא היישום הידוע של פרדיגמת Scatter-Gather, שנחשב היום אמנם כבוגר – ומובן היטב.

הרעיון הוא לחלק את החישוב המבוזר לשני שלבים:

  • Map – עיבוד נתונים נקודתי על המכונה הלוקאלית (חיפוש / פילטור / עיבוד נתונים וכו’)
  • Reduce – ביצוע סיכום של החישוב וחיבור התשובות של המחשבים הבודדים לתשובה אחת גדולה.
החלוצים בתחום של Map Reduce מבוזר על פני מספר רב של מחשבים הם חברת גוגל, ופרויקט Apache Hadoop – שהושפע רבות ממאמרים שגוגל פרסמה על מימוש ה Mapreduce שלה. בעשור מאז הושק הפך פרויקט Hadoop לסטנדט בתעשייה, עם קהילה עשירה ורחבה. כאשר הרווחים מתמיכה ב Hadoop הגיעה למאות מיליוני דולרים בשנה – נכנסו לשם גם שחקני ה Enterprise הגדולים (כלומר: EMC, IBM, Oracle, וכו’)
.
Google Map-reduce ו Hadoop מבוססים על מערכת קבצים מבוזרת (GFS ו HDFS בהתאמה), ותשתית לביצוע חישוב מבוזר על גבי ה nodes שמחזיקים את הנתונים הנ”ל (ב Hadoop נקראת YARN, בגוגל כנראה פשוט “Mapreduce”).
 
בפועל יש ב Map reduce שלושה שלבים עיקריים: Reduce, Map ו Shuffle (העברת סיכומי הביניים בין ה Mappers ל Reducers – פעולה אותו מספק ה Framework).
 
דוגמה לבעיית מיון מבוזרת (הניחו שמדובר במיליארדי רשומות) הנפתרת בעזרת MapReduce. המפתחים כותבים את פונקציות ה Map וה Reduce, ה framework מספק להם את ה Shuffle (העברת הנתונים בין ה mappers ל reducers).

ניתן לכתוב פונקציות “Map” ו “Reduce” בקוד, אך סביר יותר להניח שכאשר אתם מגדירים חישובי Map-reduce רבים – תעדיפו להשתמש ברמת הפשטה גבוהה יותר כגון אלו שמספקים Pig (מן “שפת תכנות” מיוחדת ל Map-Reduce) או Hive (המבוסס על SQL).

כדרך אגב: Pig קיבל את שמו מכיוון שחזירים אוכלים גם צמחים וגם בשר – ו Pig יודע לטפל גם ב structured data וגם ב unstructured data.

השנים עברו, וכיום המודל של חלוקת החישוב המבוזר לשלבי Map ו Reduce  – נחשב מעט מוגבל.
 
כמו כן, ההסתמכות על מערכת קבצים כבסיס לחישוב היא טובה ל DataSets ענק שלא ניתן להכיל בזיכרון (יש clusters של Hadoop שמנתחים עשרות, ואולי מאות PetaBytes של נתונים), אבל בעשור האחרון הזיכרון הפך לזול (מכונה עם 1TB זכרון היא בהישג יד) – והיכולת לבצע את החישוב בזיכרון יכולה להאיץ את מהירות החישוב בסדר גודל או שניים, ואולי אף יותר (תלוי בחישוב). עובדה זו מקדמת את הפופולריות של הפתרונות לחישוב מבוזר מבוסס-הזיכרון (כמו Storm, או Spark), ומשאירה ל Hadoop את היתרון בעיקר עבור מאגרי הנתונים הבאמת-גדולים (נאמר: 100TB ויותר של נתונים, מספר שבוודאי ישתנה עם הזמן).
 
המוצרים העיקריים ב Eco-System של Hadoop
 

דוגמה נוספת לדפוס של Scatter – Gather הוא הדפוס בו עושים שימוש ב Spark. אני לא בטוח שזהו שם רשמי – אך אני מכיר את המינוח “Transform – Action” (כאשר “map” הוא פעולת transform אפשרית, ו “reduce” הוא action אפשרי).

Spark הוא הכוכב העולה של עולם ה Big Data. בניגוד ל Hadoop הוא מאפשר (כחלק מהמוצר) מספר רב יותר של פונקציות מאשר “map” ו “reduce”.
במקום פעולת ה map ניתן להשתמש בסמנטיקות כגון map, filter, sample, union, join, partitionby ועוד…
במקום פעולת ה reduce ניתן להשתמש בסמנטיקות כגון reduce, collect, count, first, foreach, saveAsXxx ועוד.

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

המוצרים ב Eco-System ה מתהווה של Spark (חלקם מקבילים לכלים קיימים של Hadoop). מקור: databricks

ל Spark יש עוד שתי תכונות חשובות:

  • הוא מחזיק (סוג של Cache) את הנתונים בזיכרון – אליו הגישה מהירה בסדרי גודל מאשר בדיסק.
  • הוא מרכז את רוב שרשרת החישוב באותו node ומצמצם את הצורך להעביר נתונים בין nodes ב cluster (גם ל Hadoop יש כלים שעוזרים לצמצם העברות של נתונים בין nodes, אך Map-reduce פחות מוצלח בכך באופן טבעי)
פרטים נוספים:
  • ה “agent” של Spark רץ במקביל למערכת ה storage המבוזר, תהיה זו Hadoop או Cassandra (או סתם קבצים בפורמט נתמך) – ושואב ממנו את הנתונים הגולמיים לחישוב.
  • ה Agent (נקרא node – אני נמנע משם זה בכדי למנוע בלבול) מקבל Job (לצורך העניין: קטע קוד) לבצע חישוב מסוים על הנתונים. יש כבר ב Agent קוד של פונקציות שימושיות (filter, sort, join, וכו’ – לפעולות “map” או count, reduce, collect – לפעולות “reduce”).
  • ה Agent מחלק את המשימה ל stages ובונה גרף חישוב (על בסיס הידע כיצד מאורגנים הנתונים ב cluster) – ושולח tasks חישוביים ל Agents ב cluster.
ל Spark יש לא מעט נקודות אינטגרציה עם Hadoop – כך שהתחרות באמת היא לא בין Hadoop ל Spark (לפחות – עדיין), אלא יותר תחרות בין Spark ל YARN (מנוע ה Map-reduce).

 

Event Processing

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

זן אחר של חישוב הוא חישוב ב Streaming: ביצוע חישובים קטנים רבים, כחלק משטף של אירועים שנכנס למערכת.
בקטגוריה זו ניתן לכלול את Spark Streaming (המבוסס על Spark), אך אתמקד דווקא ב Storm – שנבנה לצורך זה במקור.

Storm

  • מערכת Horizontal scalable ו fault-tolerant – כמובן!
  • מערכת המספקת תשובות ב low-latency (שלא לומר real-time – כי זה פשוט לא יהיה נכון), תוך כדי שימוש בכוח חישוב מבוזר.
  • At-lest-once Processing מה שאומר שהנחת היסוד במערכת המבוזרת היא שחלקים שלה כושלים מדי פעם, ולכן לעתים נעשה אותו חישוב יותר מפעם אחת (לרוב: פעמיים) – בכדי להמשיך לקבל תוצאות גם במקרה של כשל מקומי.

Storm נולדה מתוך פרויקט בטוויטר לחישוב trending analysis ב low-latency.

המבנה של Storm Computation Cluster הוא סוג של Pipes & Filters, כאשר יש:

  • Stream – רצף של tuples של נתונים.
  • Spout – נקודת אינטגרציה של המערכת, המזרימה נתונים ל streams.
  • Bolt – נקודת חישוב (“Filter”) בגרף החישוב (“הטופולוגיה”).
    על מערכת Storm מריצים טופולוגיות חישוב רבות במקביל – כל אחת מבצעת חישוב אחר.
  • Supervisor – הוא node של Storm, שכולל כמה Workers שיכולים להריץ את קוד ה bolts או ה spouts.
  • Stream Grouping – האסטרטגיה כיצד לחלק עבודה בין bolts שונים.
בעוד פעולות אצווה סורקות את הנתונים מקצה אחד לקצה שני – וחוזרות עם תשובה (“42”), ב Event Processing כל הזמן נכנסים נתונים, והערך אותו אנו מחשבים (אחד או יותר) – יתעדכן באופן תדיר (“43, לא רגע… עכשיו 47… ועכשיו 40…”).
 
טופולוגיה לדוגמה של Storm. מקור: michael-noll.com
 

אם העבודה היא חישובית בלבד – כל אחד מה supervisors יוכל להריץ את כל הטופולוגיה (ואז לא צריך להעביר נתונים בין מחשבים במערכת – שזה עדיף). נוכל לבחור, למשל, ב Local Stream Grouping – שמורה ל Storm לשלוח את הנתונים ל Worker על אותה המכונה.

במידה ויש נתונים מסוימים שיש להשתמש בהם לצורך החישוב, והם נמצאים על supervisors מסוימים – יש להגדיר את Stream Grouping כך שיידע לשלוח את הנתונים ל supervisor הנכון. במקרה כזה אולי נרצה לבחור ב Fields Stream Grouping – המורה ל Storm לשלוח את הנתונים למחשב ע”פ שדה מסוים בנתונים (למשל: “ארץ” – כי כל supervisor מחזיק נתונים של ארץ אחרת).
 
הערכה גסה איזה כלי יכול להתאים לכם – בהינתן בזמני ההמתנה לתשובה שאתם מוכנים לסבול. * Tez הוא מנוע שכולל שיפורים ל Map-Reduce, שמרביתם מזכירים את הארכיטקטורה של Spark – מלבד הגמישות לתאר תהליכים כיותר מ-2 שלבים עיקריים.

 

Mahout

ארצה להזכיר בקצרה את Apache Mahout (שהוא חלק מ Hadoop), פירוש השם Mahout הוא “נהג הפיל” – ואכן Mahout רוכבת על הפיל (Hadoop).
זהו כלי שמספק סט של אלגוריתמים שימושיים הממומשים בצורה מבוזרת, חלקם על גבי Map-Reduce וחלקם על גבי Spark – ומאפשר לעבוד ברמת הפשטה גבוהה אפילו יותר.

סוגי הבעיות ש Mahout מכסה (כל אחת – בעזרת כמה אלגוריתמים שונים) הן:

  • סינון שיתופי – “אנשים שאהבו את x אהבו גם את y”
  • Classification – אפיון “מרחב” הנתונים מסוג מסוים – גם אלו שאין לנו. סוג של חיזוי.
  • רגרסיות – הערכת הקשרים בין משתנים שונים.
  • Clustering – חלוקה של פריטי מידע לקבוצות – ע”פ פרמטרים מסוימים.
  • ועוד
מימושים של האלגוריתמים  הנ”ל תוכלו למצוא בקלות למכונה יחידה, אבל אם יש לכם סט גדול של נתונים, או שאתם רוצים לחשב את האלגוריתמים בצורה תכופה – Mahout יחסוך לכם עבודה רבה!
 
 
 

.

Lambda Architecture

הכלים שהצגנו למעלה – מאפשרים לנו בחירה בין:

  • תשובה מדויקת – אטית (למשל: Map-reduce)
  • תשובה “לא מדויקת” – מהירה (למשל: Storm או Spark)
    בהנחה שאנו מקריבים דיוק עבור המהירות. למשל: משתמשים בחישוב בנתונים בני חמש דקות – ולא העדכניים ביותר, או חישוב על סמך דגימה חלקית – ולא על סמך כלל הנתונים.

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

סוג של שילוב מקובל בין 2 הגישות נקרא “ארכיטקטורת למבדה”, ספק אם על שם האות היוונית למבדה (Λ) שאם מטים אותה על הצד מזכירה מאוד את צורת הארכיטקטורה – ואולי בהקשר ל Lambda Calculus המבוססת על פישוט המערכת לפונקציות (בהקשר של תכנות פונקציונלי). הנחות היסוד של הארכיטקטורה הן:

  • מייצרים במערכת התפעולית שטף של אירועים – כולם immutable (בתרשים למעלה: “new data stream”).
  • את האירועים אוספים ומפצלים ל-2 ערוצים:
    • ערוץ של שמירה לטווח ארוך – נוסח HDFS או AWS S3, ואז ביצוע שאילתות ארוכות באצווה (Batch).
    • ערוץ של עיבוד מיידי והסקת תובנות – נוסח Storm, שבו ההודעות ייזרקו מיד לאחר שיעובדו (הן שמורות לנו מהערוץ הראשון) – הערוץ המהיר.
  • את התובנות קצרות הטווח של הערוץ המהיר, ואת התובנות ארוכות הטווח – של ערוץ האצווה מרכזים ל storage שלישי (Service Layer) – לרוב HBase, Impala או RedShift, ממנו נבצע שליפות חזרה למערכת התפעולית.

כמו ארכיטקטורה, “ארכיטקטורת למבדה” היא רק תבנית מקובלת – ונכון יותר יהיה להתאים אותה לצרכים הייחודיים שלכם, ולא להיצמד בכוח לאיזו הגדרה מקובלת..

Apache Kafka

לסיום אני רוצה להזכיר עוד מערכת מבוזרת שהופכת פופולרית – Distributed Message Queue בשם קפקא.

בדומה למערכות הקודמות, קפקא היא מערכת Horizontally scalable ו Fault-tolerant.
בנוסף יש לה מימד של durability – הודעות נשמרות לדיסק ומשוכפלות בין מחשבים שונים.

בקפקא נלקחו בה כמה החלטות תכנוניות בכדי לתמוך בשטף אדיר של אירועים. קפקא מטפלת יפה בקצבים גבוהים מאוד של נתונים, במחיר של latency מסוים בכתיבת ובשליפת הודעות. שמעתי על חבר’ה שחווים latency אף של ל 2-3 שניות.

כלל-אצבע ששמעתי אומר כך: “אם יש לך עד 100,000 הודעות בשנייה – השתמש ב RabbitMQ, אם יש יותר – כדאי לשקול מעבר לקפקא”.

 

כמה הנחות בעולם של קפקא הן:

  • הודעות ב Queue הן immutable – בלתי ניתנות לשינוי. ניתן להוסיף הודעות ל queue – ולקרוא אותן, אך לא לעדכן או למחוק אותן. ההודעות יימחקו כחלק מתהליך של ה Queue (למשל: לאחר 24 שעות) – והצרכן צריך לרשום לעצמו ולעקוב אלו הודעות כבר נקראו – כדי לא לקרוא אותן שוב. הן פשוט יושבות שם – כמו על דיסק.
    קפקא מנהלת את ההודעות כקובץ רציף בדיסק – מה שמשפר מאוד את יעילות ה I/O שלה. כל הפעולות נעשות ב Bulks.
  • ה Queue נקרא “Topic” ולא מובטח בו סדר מדויק של ההודעות (פרטים בהמשך).
  • Broker הוא שרת (או node) במערכת. אם לברוקר אין מספיק דיסק בכדי לאכסן את תוכן ה Topic, או שאין לו מספיק I/O בכדי לכתוב לדיסק את ההודעות בקצב מהיר מספיק – יש לחלק (באחריות ה Admin האנושי) את ה topic על גבי כמה partitions. ההודעות שמתקבלות ישמרו על partitions שונים, וקריאת ההודעות – גם היא תעשה מה partitions השונים.
קפקא עצמה מאוד מרשימה מבחינת יציבות וביצועים – אך זה נעשה במחיר אי-החבאת מורכבויות של מימוש מהמשתמשים שלו:
 
ה producer צריך לדעת על מספר ה partitions שבשימוש, מכיוון שקפקא מסתמך על כך שהוא עושה בעצמו מן “Client Side Load Balancing” (דומה לרעיון של Client-Side Directory שהסברתי בפוסט הקודם) – ומפזר את ההודעות בין ה partitions השונים (או שכל producer עושה זאת בעצמו – או שהם עושים זאת – כקבוצה).
הפיזור כמובן לא צריך להיות אקראי אלא יכול להיות ע”פ שדה מסוים בהודעה, שדה כמו “ארץ” – שיש לו משמעות עסקית.
 
ה consumer לא יכול לקרוא את ההודעות ב topic ע”פ הסדר – כי הן מפוזרות בין ה partitions השונים (קריאה נעשית רק מ partition מסוים). אין שום מנגנון בקפקא שמסייע להבין באיזה partition נמצאת ההודעה הבאה. בפועל מה שעושים הוא שמציבים consumer לכל partition – והם מעבדים את ההודעות במקביל, מבלי להתייחס להודעות שב partitions האחרים.
כמו כן – מישהו צריך לעקוב מהי ההודעה האחרונה שנקראה מכל partition: קפקא לא עושה זאת. הדרך המקובלת לעשות זאת היא להיעזר ב Zookeeper לניהול ה state המבוזר הזה (שיהיה יציב, זמין, וכו’).
ב AWS Kinesis (וריאציה של Kafka – של אמזון) – מנהלים את ה state המבוזר ב DynamoDB (בסיס נתונים K/V – גם הוא מבוזר).
 
כל partition ממספר את ההודעות של ה topic באופן בלתי-תלוי. מקור: kafka.apache.org
 
לא מתאים לכם? – אתם יכולים לסדר את המידע בחזרה בעזרת מערכת נוספת שתעשה את העבודה (למשל: Storm?).
 
לכל Broker יש רפליקה (אחת או יותר), במבנה של Active-Passive. ה Active משרת את ה consumer – ואם הוא כושל, אחד ה Passives נבחר להיות ה leader – והופך להיות “ה Active החדש”.
 
ה producer הוא האחראי על מדיניות ה consistency ויכול לבחור להחשיב כתיבה ל queue כמוצלחת כאשר ה Leader קיבל אותה, או רק כאשר ה Leader סיים לעשות רפליקציה של הנתונים ל broker נוסף (אחד או יותר – תלוי ברמת הפרנויה שלכם). התוצאה כמובן היא trade-off בין latency ל durability – שניתן לשחק בו בצורה דינאמית.
 
אפשר להשוות את קפקא למשאית: היא מאוד לא נעימה לצורך יציאה לדייט עם בחורה, או בכדי לקנות משהו בסופר.
אבל אם אתם רוצים להעביר אלפי טונות של מוצר כלשהו – בוודאי שתרצו כמה משאיות שיעשו את העבודה. צי של רכבים קטנים – פשוט לא יעשה עבודה טובה באותה המידה…

 

סיכום

בפוסט אמנם הצגתי הרבה מוצרי “Big Data” – אך הכוונה הייתה להתמקד באספקטים המבוזרים שלהם.
מערכות מבוזרות מוסיפות סיבוך למערכת – ולכן כדאי להימנע מהן במידת האפשר. כן… ברור לי שלא-מעט מהנדסים מחפשי-אתגר ימצאו את הדרך להשתמש במערכות מבוזרות – גם שאין צורך עסקי לכך.

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

שיהיה בהצלחה!

—-

לינקים רלוונטיים:
השוואה בין Spark ל YARN

מצגת טובה אודות Spark

שלום, מונגו! (MongoDB)

לפני כחודשיים, בערך, התרחש מהפך קטן-גדול.לא, אני לא מדבר על מה שקרה (וקורה, בעת כתיבת הפוסט) באוקראינה. גם לא על נתח השוק שמאבדת מייקרוסופט בהתמדה, או על החדירה של אינטל ל high end האמיתי של החומרה. דווקא החברה שמפנה במקרה זה את מקומה היא לא אחרת מאשר הענק הכחול – IBM, והיא עשויה לא-להיות האחרונה.

בסיס נתונים לא-רלציוני, בשם MongoDB תפס את המקום החמישי הנחשק במדד הפופולריות של DB-Engine, ובעצם הפך לבסיס הנתונים הלא-רלציוני הראשון שנכנס לחמישייה הפותחת [א].

יש היגיון מסוים בכך שדווקא MongoDB הוא הראשון מבין בסיסי הנתונים מסוג NoSQL לפרוץ לרשימת בסיסי הנתונים הרלציוניים: מבחינות מסוימות הוא קצת יותר דומה להם: יש לו (יחסית ל NoSQL DB) עושר רב של יכולות, וותק, וזמינות של תמיכה מסודרת (לאחרונה גם בישראל) – הכוללת “גרסאות Enterprise”.

האופן בו אנשי מונגו אוהבים להציג את בסיס הנתונים: מעט פחות יכולות והרבה יותר Scalability מ RDBMS + הרבה-הרבה יותר יכולות מבסיסי נתונים NoSQL אחרים…

מקור השם של מונגו הוא מהמילה humongous (גדול, אדיר), אולם היכולת לטפל בכמויות גדולות של Data היא כנראה לא התכונה הבולטת, המושכת אליו כ”כ הרבה מפתחים. בעולם ה Internet Scale דווקא אני שומע קולות שמחשיבים את Mongo כבסיס נתונים בעל יכולות Scale מתונות.

הפופולריות של MongoDB (בקיצור: “מונגו”) נובעת מהקלות שהוא מספק למפתחים בעזרת הסכֶמה (db schema) הגמישה שלו. לא עוד Migrations, או יותר גרוע: תקלות migration על סביבת production (המוכרות כנראה היטב לכל מי שעבד עם SQL בסביבת ה Enterprise).
מונגו הופך להיות מועמד לקחת את מקומו של MySQL כבסיס נתונים זול ויעיל ל”משימות רגילות” – ויש הרבה מאוד כאלו.

הבהרה חשובה: מונגו הוא לא תחליף ישיר ל RDBMS. הוא שונה. כאשר זקוקים להרבה joins על נתונים, ופעולות רוחביות (“SELECT”) על הרבה אובייקטים – מונגו (או Document-Based Database אחר) כנראה לא יתאים. מונגו מתאים כאשר יש אובייקטים עצמאיים (“לקוח”, “אתר”, “משלוח”), ורוב הפעולות נעשות על האובייקטים הבודדים – ורק מיעוט הפעולות הן רוחביות (“כל המשלוחים שיצאו אתמול ויגיעו מחר”).

סקר המראה מה מושך מפתחים ב NoSQL: לא, זהו לא ה Scale במקום הראשון – אלא דווקא הגמישות. מקור

בפוסט זה אינני מתכוון לגעת בנושאים של Scalability או Availability של מונגו או בכלל ,לא הקדמה כללית ל NoSQL (נתתי כזו פעם, היא עדיין רלוונטית דייה) ולא דיון על ה CAP theorem.

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

… עוד קיטלוג של בסיסי נתונים NoSql

מונגו DB – מי זה הבחור הזה? 

ראשית הייתי רוצה להזכיר בכמה מילים את מודל ה Document-Based Database בכלל, ואת זה של מונגו בפרט.
אם נשווה את המודל של Mongo לבסיס נתונים רלציוני ההשוואה תראה בערך כך:

מונגו מנהל מספר בסיסי נתונים, ממש כמו RDBMS. יש אוספים של “מסמכים” (ניתן לחשוב עליהם בשלב זה כמחרוזות של JSON). בתוך ה JSON יש ערכי key:value (= שדות) שמונגו מודע להם (בניגוד לבסיס נתונים K/V – שם הוא לא).

ניתן ליישם הדמייה ל KVDB (בסיסי נתונים מסוג K/V) על גבי RDBMS בכך שמייצרים טבלה עם 2 עמודות: ID ו BLOB של נתונים (למשל: קובץ JSON).

באופן עקרוני, בסיס הנתונים הרלציוני יספק את היכולת הבסיסית של KVDB, אך ללא הביצועים / Scalability / זמינות שניתן לקבל מבסיס נתונים KVDB. הוא עתיד “להתפרק” אחרי מאות מיליונים ספורים של רשומות והקצב בו הוא ישרת את לקוחותיו לא הולך להיות מרשים במיוחד.

בסיס נתונים מבוסס מסמכים (בקיצור DBDB) הוא כמו[ב] KVDB עם 2 הבדלים משמעותיים נפוצים:

  • הוא מכיר את תוכן המסמך, והפורמט שלו – והוא מאנדקס חלקים ממנו, לצורך Queries רוחביים יעילים ו/או מתוחכמים.
  • לעתים קרובות: הוא מאפשר הגדרת קשרים (למשל: היררכי) בין המסמכים.
אפשר גם “לקמבן” התנהגות כזו בעזרת RDBMS בעזרת כמה stored procedures, מה שעשוי ליצור יישום יעיל אפילו פחות מ”חיקוי ה KVDB” שתארתי למעלה.

דייט ראשון – התקנה וכלים ראשוניים

ההתקנה של מונגו היא פשוטה למדי:

  • פתיחת ZIP הכולל את קבצי ה exe. לאיזו תיקיה (ב”חלונות”).
  • יצירת תיקיה ריקה בשם data/db/ (יחסית לכונן בו מונגו מותקן) – התיקייה בה מונגו מאכסן את ה data שלו. ניתן לקנפג תיקיה אחרת, כמובן.
בין קובצי ה exe ניתן למצוא כמה מעניינים:
  • mongod.exe – השדון החרוץ (daemon [ג]) של בסיס הנתונים. כלומר: התהליך המרכזי.
  • mongo.exe – ה Admin Shell, דרכו ניתן לבצע פעולות רבות.
  • mongoexport.exe – פעולות import/export של קבצי נתונים (BSON).
  • mongodump.exe/mongorestore.exe – גיבוי / אחזור של בסיס הנתונים (כקובץ בינארי דחוס).
  • mongostat.exe – תהליך שאוסף נתונים על השימוש ב mongo.
בגדול, כדי להפעיל ולנסות את mongo בצורה קלה יש פשוט להפעיל את mongod.exe ואחריו את mogno.exe. דרך ה console ניתן לבצע / לנסות את רוב הפעולות המשמעותיות של בסיס הנתונים – ולקבל פידבק מהיר.

בואו ננסה משהו:

  1. ביקשנו לראות אלו בסיסי נתונים קיימים בעזרת פקודת show dbs. בסיס הנתונים היחידי הקיים הוא local, למרות שמונגו חיבר אותנו בכניסה ל test – בסיס נתונים ריק. מונגו הוא לעתים רבות עצלן, וייצור אובייקטים מבנים רק כאשר יש בהם תוכן ממשי.
  2. השתמשנו ב use בכדי לעבור לבסיס נתונים חדש (שעדיין לא קיים). מונגו יזכור אותו, אך עדיין לא ייצור אותו.
  3. פקודת db בודקת באיזה בסיס נתונים אנו כעת.
  4. נתחיל בהכנסות: נכניס לתוך אוסף שעדיין לא קיים (people), בבסיס הנתונים שעדיין לא קיים (“db” הוא האובייקט המייצג את בסיס הנתונים הנוכחי) רשומה – כלומר מסמך, המתאר את ג’ון.
    ברגע זה מונגו ייצור את בסיס הנתונים ואת האוסף (collection) בשם people – ויכניס לתוכו את הרשומה.שימו לב שמונגו יקצה קובץ בשם data/db/myNewDb.0 בו הוא יאכסן את בסיס הנתונים. למרות שיש לי רק מסמך אחד קטן – מונגו בחר להקצות אצלי כ 200MB בדיסק – מה שעשוי להראות קצת מבהיל. הסברים – בהמשך הפוסט.

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

  5. בשלב זה אני בודק אלו אוספים יש בבסיס הנתונים: מכיוון שבסיס הנתונים נוצר – האוספים כבר קיימים (people ואוסף האינדקסים – שמכיל רשומות ראשוניות בלבד). בדומה ל RDBMS, מונגו משתמש בעצמו כדי לנהל מידע מערכת.
  6. אני אבצע שאילתה (מקבילה ל * SELECT) על אוסף האנשים.
    הממ… אני לא זוכר שהכנסתי שדה בשם id_, אתם זוכרים?!

סביבת ה shell, כדרך אגב, היא javaScript לכל דבר – וניתן להשתמש ביכולות ה JavaScript שאתם מכירים (var, פונקציות ועוד).

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

שדה ה id_

כפי ששמתם לב מונגו הוסיף לנו שדה בתוך המסמך בשם id_. הוא יוסיף שדה זה אם לא הגדרנו אותו בעצמנו (בד”כ נשאיר זאת לו).

מבנה ה id_

תכונה מעניינת של ה id_ (נקרא גם object id) היא שה timestamp הוא ראשון, מה שמאפשר לבצע מיון של אובייקטים ע”פ זמן היצירה, בקירוב. הזמן נשמר ע”פ epoch[ה] של unix.

בבסיסי נתונים מסוג KVDB ו DBDB יש חשיבות לא-מעטה לדרך בה בונים את ה ids/keys:

  • ה key הוא לעתים קרובות המפתח ל partitioning, ויכול להשפיע רבות על הביצועים.
  • יעילות של ה hash function יכול להיות משמעותי כאשר מדברים על המון פעולות בשנייה.
  • מה קורה כאשר שני ids מתמפים לאותו אובייקט? זה לא סביר כאשר יש אלפי ערכים – אך סביר יותר, כאשר יש מיליארדים.

חיפוש ואינדקסים

במונגו, ניתן לחפש אחר ערכים בתוך collection בעזרת פקודת find, למשל:
db.persons.find({ lastname: 'Smith' });
החיפוש נעשה ע”י “דוגמה” או prototype: אנו מספקים את הערכים שאנו מחפשים ומונגו יחזיר לנו cursor המצביע על האובייקטים שמכילים את הערכים הללו.
ניתן לעשות חיפוש קצת יותר כללי, בעזרת query modifiers המספקים יכולות מספריות / לוגיות, למשל:
db.persons.find( { childrenCount: { $gt: 3 } } );
gt$ הוא קיצור של greater than, כלומר: אנשים בעלי 3 ילדים או יותר. שדה שלא הוגדר באובייקט (כלומר: מסמך) מסוים, יהיה בעל ערך 0 – לצורך העניין. יש גם query modifiers נוספים כגון min$ או or$ ועוד.

אפשר לחפש על אובייקטים מקוננים, למשל address.city או להגדיר שאילותות מורכבות הכוללת מספר רב של שדות או query modifiers לדוגמה:

db.persons.find( { childrenCount: { $gt: 3, $lt 20 } } , { 'address.city': 'Holon' } );
הערה: הסיבה ששמתי את address.city בתוך מרכאות נובעת מג’אווהסקריפט. שימוש בנקודה איננו תקני במפתח של אובייקט.אפשר גם לצמצם את התשובה לשדות מסוים (בדומה ל RDBMS select) בעזרת אובייקט projection – אותו מגדירים בפרמטר השני של הפקודה find:

db.persons.find({ lastname: 'Smith' }, { tile:1, lastname: 1 });

בדוגמה זו אנו רוצים לקבל רק “תואר” ושם משפחה. ערכי ה “1” הם דרך מקוצרת לכתוב true – כלומר: החזר לי את השדה הזה. שימו לב: השדות צריכים להיות כולם true או כולם false – לא ניתן לערבב. יוצא הדופן היחיד הוא השדה id_, אותו ניתן להשמיט גם כאשר יש רשימה “פוזיטיבית” של שדות בהם מעוניינים.

מה עוד ניתן לעשות ב queries? ניתן לעשות הרבה. אציין שליפת מספר קבוע-מראש של ערכים מתוך מערך במסמך (נאמר תגובות בבלוג: רק 10 תגובות ראשונות מכל פוסט), או את היכולת לעשות שאילתות קיבוץ מורכבות (db.collection.group) – ולהוסיף להן פונקציות פילטור בג’אווהסקריפט, ad-hoc.

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

בעולם ה NoSQL עושים הפרדה בין “planned Queries” ו “Ad-hoc Queries”.
Planned Queries הן כאלו שהתכוננו אליהן, לרוב בעזרת יצירת אינדקסים (פנימיים או חיצוניים לבסיס הנתונים), בעוד Ad-hoc Queries הן כאלו שעושים בצורה “ספונטנית” – ללא קיום של אינדקסים, pre-fetch או כל הכנה מקדימה.

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

אינדקסים

 
הגדרה של אינדקסים היא פשוטה למדי, דומה להגדרת החיפוש:
db.persons.ensureIndex( { firstname: 1 } );
ייצור אינדקס לשדה ה firstname.
db.person.ensureIndex( { "address.city" : 1 } );
ייצור אינדקס לשדה city בתוך תת-האובייקט (או המסמך) address. כמו כן:
db.person.ensureIndex( { lastname: 1, firstname: 1} );
ייצור אינדקס של מפתח המורכב מ2 שדות: שם פרטי, ושם משפחה.
התחביר ensureIndex מצביע על כך שאם אינדקס קיים – מונגו לא ישכפל אותו.
יש עוד אפשרויות אינדוקס רבות, עליהן ניתן לקרוא בתיעוד הרשמי.
מבני הנתונים המשמשים את מונגו. מקור

אכסון (Persistency)

שאלה שבוודאי מעניינת מאוד את מי שמגיע מרקע והבנה כיצד עובד RDBMS היא “מה קורה שם בתוך מונגו?” או “כיצד ממימשו זאת?”.
בחלק זה אנסה לענות על שאלה זו בקיצור.מונגו כתוב ב ++C וש לו הפצות למערכות הפעלה שונות. מערכת ההפעלה אליה הוא תוכנן במקור היא Unix/Linux (כלומר: מערכת POSIX). יוצרי מונגו לקחו כמה החלטות Design מהותיות:

  1. מונגו יעבוד קודם כל עם זיכרון (עבור המהירות). מונגו אוהב זיכרון, והרבה!
    כל בסיס נתונים שמכבד את עצמו מרוויח מזיכרון, אך כשלמונגו חסר זיכרון – נפילת הביצועים היא משמעותית מאוד.
  2. עדכון של הזיכרון לדיסק יינתן (delegated) למערכת ההפעלה. התכנון המקורי התבסס על הדרך בה מערכת Linux עובדת, וספציפית פקודת mmap למיפוי קבצים – ישירות לתוך הזיכרון. המימוש עבור מערכת ההפעלה “חלונות” הוא כנראה דומה (במסגרת הכלים ש”חלונות” מספקת), אך ידוע כפחות יעיל.
    היתרונות של גישה זו היא קלות פיתוח שמונגו הרוויח, ואי שכפול caches בין מערכת ההפעלה למונגו (מה שמנצל את הזיכרון בצורה יעילה יותר). החיסרון: המנגנון מאחורי mmap הוא כללי ואינו האופטימלי-ביותר לצרכים של מונגו.
  3. למונגו יש רמות “durability” שונות הניתנות לקנפוג. האם כתיבה לבסיס הנתונים תכנס לתור של כתיבה לדיסק (“fire and forget” – דומה ל INSERT_DELAYED של MySQL) או האם כל כתיבה נכתבת במקום ל journal על הדיסק (“fully safe”). ברירת המחדל היא “fire and forget”.

מונגו מאכסן כל Database בסדרת קבצים. הקבצים מתחילים בקובץ בגודל 64MB (למשל db.0) ומכפילים את עצמם בכל פעם (128MB – עבור db.1 ואז 256MB עבור db.2) וכו’ עד שמגיעים לגודל של 2GB – ונשארים שם. מונגו מקצה יותר מקום ממה שנדרש למידע בפועל – כדי לא “להתקע” באמצע רצף של כתיבות. במערכת ההפעלה שלי הוא מקצה 200MB לכל בסיס נתונים שרק נוצר.

את הקבצים עצמם מונגו מחלק ל Extents – מן בלוקים הכוללים data או אינדקסים של collection מסוים (לא מערבבים סוגים ולא מערבבים collections).
גם בתוך extent של data, מונגו שומר לכל document מעט Padding – כלומר: יותר מקום ממה שנדרש, במידה והמסמך יגדל במעט. לדוגמה: עדכון של שדה לערך ארוך יותר או הוספה של שדה. המסמכים וה extents הם רציפים בדיסק / זכרון.

db.collection.dataSize();
יספק לנו מידע מה גודל ה collection בבתים, עבור המסמכים וה paddings שלהם.
db.collection.storageSize();
יספק לנו את גודל ה data extents של ה collection. כלומר ()dataSize ועוד מקום שהוקצה בדיסק ועדיין לא בשימוש.
db.collection.totalIndexSize();

יספק לנו את גודל ה index extents של ה collection, כולל שטחים ב extents שעדיין לא בשימוש.

סטטיסטיקות נוסף ניתן לקבל בעזרת אובייקט ה dbStat.

מונגו משתמש בפקודת mmap של לינוקס בכדי למפות extents (בלוקים בקבצים) לזיכרון. הקבצים הם כמו “גדר הגנה” בפני fragmentation שיכולה להיווצר באופן טבעי במערכת הקבצים.

כאשר מסמכים גדלים מעבר ל padding הקיים – הם מועברים למקום חדש עם padding חדש. מונגו לומד את קצב השינויים ב collection ולפיו מבסס את ה padding factor לפיו יקבע גודל padding חדש. גדילות תכופות של מסמכים –> paddings גדולים יותר.

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


fragments בתוך extents של מונגו. מקור.


הפתרון בעיקרון הוא לבצע de-fragmantation בעזרת פקודת compact.

הקושי:  למונגו יש thread יחיד לכתיבות, ופעולת compact תתקע את בסיס הנתונים כולו לזמן מה (כלומר: down time). אפשר לתזמן פעולות תחזוקה אלו או אפשר, בעזרת replication של nodes של מונגו – לעשות את זה offline.
זה כנראה לא מה שהייתם מצפים מ”בסיס הנתונים מהדור החדש” – אבל ככה זה.
עוד נקודה כואבת במונגו היא נעילות (לצורך consistency):
נעילות הן ברמה של בסיס נתונים (database). עד גרסה 2.1 – נעילות בכלל היו ברמת כל ה instance של מונגו. ישנן תוכניות לעתיד לשפר את רמת הנעילה במונגו.
המשמעות היא כמובן מגבלה משמעותית לביצוע כתיבות ב scale, לפחות כאשר אנו עובדים ברמת durability (או safety) גבוהה.
הברירה היא בין לוותר על מידה מסוימת של durability, לצמצם כתיבות, או להשתמש ב very-high-end SSD עם IOPS (פעולות IO בשנייה) גבוה במיוחד: איזה חצי מיליון IOPS, הייתי אומר. האפשרות השלישית – חסומה בחומרה הקיימת כיום, כמובן.
ה consistency במונגו מובטח רק ברמת פעולה על מסמך – ואין להניח על סדר הפעולות בכלל המערכת (isolation).
מה קורה כאשר רוצים לבצע שינוי במסמך א’ בצורה אטומית (למשל: להגדיל ערך מספרי ב 3)?
או שמוכנים לספוג חוסר consistency מסוים, או שאפשר להשתמש בכלי מיוחד של מונגו בשם collection.findAndModify המקבלת הוראות ומבצעת שינויים במסמכים בצורה אטומית.
הפקודה תבצע שינוי אטומי במסמך אחר מסמך, אך כל פעם – במסמך בודד.
מה קורה כאשר רוצים לבצע שינוי במסמך ב’ על בסיס של נתונים ממסמך א’?
לבעיה זו אין למונגו פתרון מובנה, ויש כל מיני פתרונות מקובלים / “design patterns” כיצד לפתור את הבעיה. בגדול סט הפתרונות מתבסס על יצירת מסמך שלישי זמני בשם (מפתיע:) transaction שמסייע לנהל את הפעולה.
נקודה אחרונה מעניינת היא נושא גודל המידע. לחוסר הסכמה של מונגו יש חסרון אחד ברור: יש לאכסן את ה keys בכל פעם, מה שיכול להגדיל את גודל המידע בצורה משמעותית הן בדיסק והן ברשת (מול ה clients של מונגו).
אמנם JSON הוא מבנה נתונים יחסית יעיל, וכאשר מונגו שולח / מאכסן מסמכים – הוא בעצם משתמש בצורה בינרית יותר יעילה שנקראת BSON [ד] (קיצור של Binary JSON), אך עדיין מדובר בבזבוז.

סיכום

מונגו הוא לא בסיס נתונים מושלם, אך כנראה שהוא מספיק טוב למערכות רבות, ויכול לסייע בקיצור זמני פיתוח ותחזוקה.
ב technology stacks כמו MEAN (קיצור של Mongo, Express, Angular and Node.js) – השימוש הטבעי של מונגו ב javaScript ו JSON מאפשר לכתוב פתרון קצה-אל-קצה בשפה יחידה: javaScript.

למרות שמונגו יחסית עשיר ביכולות, יש לא מעט ספריות ODM (קיצור של Object-Document Mapping), כגון mongoose או doctrine, המסייעות במידול הנתונים או בהעשרת היכולות בשימוש במונגו.

מונגו, ומודל ה documents בכלל, טבעי מאוד לפיתוח מערכות בהן היינו משתמשים בכלי ORM: מסמך (document) הוא סוג של אובייקט, ועבודת התרגום בין שפת התכנות לשפת בסיס הנתונים, ובחזרה – נחסכת מאיתנו. ביוחד כאשר יש לפרק/להרכיב “אובייקט” יחיד מטבלאות רבות.
מונגו הוא בד”כ מהיר מ RDBMSs, לא בגלל שהמפתחים שלו חכמים יותר – אלא בגלל שהם עשו בחירות תכנוניות שמעדיפות מהירות על דברים אחרים (למשל: ההחלטה ל durability לא מושלם, כברירת מחדל). בטלו את הבחירות הללו – והפערים יצטמצמו. בעוד מימוש של KVDB הוא יחסית פשוט על גבי RDBMSs קיים (עם scale מוגבל יותר), מימוש של DBDB על גבי RDBMS הוא קשה – בגלל תהליכי האינדוקס.

כמו בסיס NoSQL רבים אחרים, מונגו מוסיף אחריות על המפתח: לדאוג לשלמות ואחידות הנתונים. מונגו העלים סט בעיות אחד מהמפתח – אך חושף אותו לסט אחר (בשאיפה: מצומצם יותר) של בעיות אחרות.
כשאתם ניגשים לעבוד במונגו – על תצפו ל Internet Scale. הוא כנראה טוב ב Scale בהרבה מ RDBMS – אך לא טוב כמו Riak או Cassandra. כמו כן אל תצפו לבגרות של RDBMS – המבוססים על מודל שכבר בעבודה במשך עשרות שנים.

בכל זאת, אם אתם מתחילים לפתח מערכת חדשה, במיוחד מערכות ווב (במידה, “המגרש הביתי של מונגו”) ובמיוחד כאלו שאינן מוגדרות היטב עדיין – יש סיכוי טוב שעם מונגו תתקדמו מהר וטוב יותר מאשר עם MySQL או PostgresDB.

שיהיה בהצלחה!

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

נעשה עדכון ב 30/3 בכדי לחדד את הנקודה שמונגו הוא לא “RDBMS מהיר” או “גמיש יותר” – הוא שונה, והוא יעיל לסוגים מסויימים של בעיות.

לינקים רלוונטיים:
מצגת מעניינת על מידול נתונים במונגו
השוואה (מעט פרובוקטיבית) בין הביצועים של מונגו ו MS SQL

—-

[א] DB-Engines קיים “כולו” שנתיים ומשהו, אבל ע”פ כל מדד מקובל – לא נראה שבסיס נתונים לא-רלציוני היה איפשהו ברשימה הפותחת ב 30 שנה האחרונות.

עוד הערה: Cassandra ומונגו נמצאים ברשימת ה top10 מאז המדד החל, אולם Sybase ASE “נדחף” ל Cassandra באמצע והחזיר אותו למקום העשירי. הסיבה היא כנראה החיזוק ש ASE קיבל מרכישת SAP את Sybase, אולם אין בכך לגרוע מהמגמה הכללית: ASE צמח בעיקר על חשבון אורקל.

[ב] ב NoSQL, כמו ב NoSQL – אין הגדרות מוסכמות או חד-משמעיות. התייחסו לכל הגדרה כ “נקודת מבט אפשרית”.

[ג] מקור המונח daemon הוא מניסוי מחשבתי בתחום התרמודינמיקה בשם Maxwell’s demon בו יש שדון שעובד ללא הפסקה ברקע ופותח דלת קטנה לחלקיקים שיעברו דרכה… daemon היא צורת כתיבה עתיקה של המילה demon (שד).

[ד] פורמט BSON גם מאפשר ניהול טיפוסים שלא קיימים ב javaScript כגון object id או date כפרמיטיב.

[ה] epoch (תאריך בסיס) הוא נקודת ייחוס ממנה שומרים תאריך בצורה מספרית, בדרך כלל בשניות. MS DOS, היתה מערכת 16bit ולא רצו לשמור תאריך, בשניות, משנת 0 (או אפילו מ 1970, כמו unix) – ולכן ה epoch הוא 1/1/1980.

כדי לתאר את התאריך 2/1/1980 (יום אחרי) – יש לשמור בשדה התאריך את המספר 24*60*60 = 86,400.

במערכת הקבצים NTFS (חלונות NT) זמן הייחוס הוא שנת 1601 – השנה הראשונה במחזור 400-השנים של לוח השנה הגרוגאני בו, שימו לב: שוחררה חלונות NT!. אפל (כתגובה?) קבעה את ה epoch של OS X לשנת 2001 – השנה בה יצאה מערכת ההפעלה OS X. בגרסאות קודמות של MAC OS, ה epoch היה שנת 1904 – שנקבעה בגלל שזו הייתה “השנה המעוברת הראשונה במאה ה-20”, ואולי כדי להתבשם בעובדה שזו הייתה מערכת שרצה על מעבדי 24 ביט (בזמן ש DOS הייתה תלויה בעבדי 16 ביט, ו epoch כזה היה מגביל אותה).