בדף הזה מוסבר איך לשפר את הביצועים של פעולות JOIN ב-Cloud Data Fusion.
פעולות JOIN יכולות להיות החלק הכי יקר בצינור. כמו כל דבר אחר בצינור עיבוד נתונים, הפעולות מבוצעות במקביל. השלב הראשון בJOIN הוא ערבוב הנתונים (shuffle) כך שכל רשומה עם אותו מפתח JOIN תישלח לאותו מפעיל. אחרי שכל הנתונים עוברים מיון (shuffle), הם מצטרפים, והפלט ממשיך דרך צינור הנתונים.
דוגמה לעיבוד מקביל בפעולות של JOIN
לדוגמה, נניח שאתם מבצעים פעולת JOIN על מערכי נתונים בשם Purchases ו-Items. כל רשומת רכישה מכילה את שם הפריט ומספר הפריט שנרכש. כל רשומה של פריט מכילה את שם הפריט ואת המחיר שלו. מתבצעת פעולה JOIN על שם הפריט כדי לחשב את המחיר הכולל של כל רכישה. כשמבצעים איחוד של הנתונים, המערכת מבצעת shuffle של הנתונים בכל האשכול, כך שרשומות עם אותו מזהה יגיעו לאותו מפעיל.
כשמפתחות JOIN מפוזרים באופן שווה יחסית, פעולות JOIN מתבצעות בצורה טובה כי אפשר להריץ אותן במקביל.
כמו בכל מיון נתונים, חלוקת נתונים לא מאוזנת משפיעה לרעה על הביצועים. בדוגמה הקודמת, הביצים נרכשות בתדירות גבוהה בהרבה בהשוואה לתרנגולת או לחלב, מה שאומר שהתהליך שמצטרף לרכישות של הביצים מבצע יותר עבודה מאשר התהליכים האחרים. אם אתם מבחינים שJOIN מוטה, יש שתי דרכים לשפר את הביצועים.
פיצול אוטומטי של מחיצות מוטות
בעזרת ביצוע שאילתות דינמי, המערכת תטפל אוטומטית בהטיות חמורות במיוחד.
ברגע שJOIN יוצר כמה מחיצות שהן גדולות בהרבה מאחרות, המחיצות האלה מתפצלות למחיצות קטנות יותר. כדי לוודא שהפעלתם את התכונה 'הפעלה אדפטיבית של שאילתות', אפשר לעיין במאמר בנושא כוונון אוטומטי.
שימוש ב-JOIN בזיכרון
אפשר לבצע JOIN בזיכרון אם אחד הצדדים של JOIN קטן מספיק כדי להיכנס לזיכרון. במצב כזה, מערך הנתונים הקטן נטען לזיכרון ואז מועבר לכל תהליך ביצוע. מערך הנתונים הגדול לא עובר ערבוב בכלל, וכך נמנעות המחיצות הלא אחידות שנוצרות כשמערבבים לפי מפתח JOIN.
בדוגמה הקודמת, קבוצת הנתונים של הפריטים נטענת קודם לזיכרון של מנהל ה-Spark. לאחר מכן, הוא משודר לכל מפעיל. מעכשיו, מנהלי ההוצאה לפועל יכולים להצטרף לנתונים בלי לבצע ערבוב של מערך נתוני הרכישות.
בגישה הזו צריך להקצות מספיק זיכרון גם ל-Spark driver וגם ל-executors כדי לאפשר להם לאחסן את מערך הנתונים של השידור בזיכרון. כברירת מחדל, Spark שומר קצת פחות מ-30% מהזיכרון שלו לאחסון הנתונים האלה. כשמשתמשים ב-JOINs בזיכרון, מכפילים את גודל מערך הנתונים בארבע ומגדירים את התוצאה כזיכרון של ה-executor וה-driver. לדוגמה, אם מערך הנתונים של הפריטים הוא בגודל של 1GB, צריך להגדיר את הזיכרון של ה-executor ושל ה-driver ל-4GB לפחות. לא ניתן לטעון לזיכרון מערכי נתונים שגדולים מ-8 GB.
הפצת מפתחות
אם שני הצדדים של JOIN גדולים מדי ולא נכנסים לזיכרון, אפשר להשתמש בטכניקה אחרת כדי לפצל כל מפתח JOIN לכמה מפתחות, וכך להגדיל את רמת המקביליות. אפשר להשתמש בטכניקה הזו בפעולות INNER JOIN ו-LEFT OUTER JOIN. אי אפשר להשתמש בו לפעולות של FULL OUTER JOIN.
בגישה הזו, הצד המוטה מומלח בעזרת עמודה חדשה של מספרים שלמים עם מספר אקראי מ-1 עד N. הצד שלא עובר שינוי מפוצל, וכל שורה קיימת יוצרת N שורות חדשות. עמודה חדשה מתווספת לצד המפוצל, ומאוכלסת בכל מספר מ-1 עד N. לאחר מכן מתבצעת פעולת JOIN רגילה, אלא שהעמודה החדשה מתווספת כחלק ממפתח JOIN. בדרך הזו, כל הנתונים שהיו מועברים למחיצה אחת מפוזרים עכשיו בין עד N מחיצות שונות.
בדוגמה שלמעלה, מקדם ההתפלגות N מוגדר ל-3. מערכי הנתונים המקוריים מוצגים בצד ימין. הגרסאות עם המלח והפיצוץ של מערך הנתונים מוצגות באמצע. הנתונים המעורבבים מוצגים בצד שמאל, עם שלושה מפעילים שונים שמצטרפים לרכישות של ביצים, במקום אחד.
כדי להשיג מקביליות גבוהה יותר, צריך להגדיל את ההפצות. עם זאת, זה בא על חשבון פיצוץ של צד אחד של JOIN, מה שגורם ליותר נתונים להתערבב באשכול. לכן, ככל שההפצה גדלה, ההטבה קטנה. ברוב המקרים, כדאי להגדיר ערך של 20 או פחות.
המאמרים הבאים
- מידע נוסף על עיבוד מקביל ב-Cloud Data Fusion