שיטות מומלצות לשימוש ב-BigQuery Storage Write API
במאמר הזה מפורטות שיטות מומלצות לשימוש ב-BigQuery Storage Write API. לפני שקוראים את המסמך הזה, כדאי לקרוא את הסקירה הכללית של BigQuery Storage Write API.
הגבלת קצב יצירת הסטרימינג
לפני שיוצרים שידור, כדאי לבדוק אם אפשר להשתמש בשידור ברירת המחדל. במקרים של סטרימינג, לסטרימינג שמוגדר כברירת מחדל יש פחות מגבלות מכסה, והוא יכול להתרחב בצורה טובה יותר מאשר סטרימינג שנוצר על ידי האפליקציה. אם אתם משתמשים בסטרימינג שנוצר על ידי אפליקציה, הקפידו להשתמש ברוחב הפס המקסימלי בכל סטרימינג לפני שאתם יוצרים סטרימינג נוסף. לדוגמה, כדאי להשתמש בכתיבה אסינכרונית.
במקרה של סטרימינג שנוצר על ידי אפליקציה, מומלץ להימנע מהפעלת CreateWriteStream בתדירות גבוהה. בדרך כלל, אם חורגים מ-40 עד 50 שיחות בשנייה, זמן האחזור של קריאות ה-API גדל באופן משמעותי (יותר מ-25 שניות). מוודאים שהאפליקציה יכולה לקבל הפעלה במצב התחלתי (cold start), מגדילים בהדרגה את מספר הסטרימינג ומגבילים את קצב השיחות של CreateWriteStream. אפשר גם להגדיר מועד אחרון ארוך יותר כדי לחכות לסיום השיחה, וכך למנוע את השגיאה DeadlineExceeded. יש גם מכסה לטווח ארוך יותר על השיעור המקסימלי של קריאות ל-CreateWriteStream. יצירת סטרימינג היא תהליך שדורש הרבה משאבים, ולכן הדרך הכי טובה להימנע מחריגה מהמגבלה הזו היא לצמצם את קצב יצירת הסטרימינג ולנצל באופן מלא את הסטרימינג הקיים.
ניהול מאגר חיבורים
השיטה AppendRows יוצרת חיבור דו-כיווני למקור נתונים. אפשר לפתוח כמה חיבורים בזרם ברירת המחדל, אבל רק חיבור פעיל אחד בזרמים שנוצרו על ידי האפליקציה.
כשמשתמשים בזרם ברירת המחדל, אפשר להשתמש בריבוב של Storage Write API כדי לכתוב לכמה טבלאות יעד עם חיבורים משותפים. ה-Multiplexing מאגד חיבורים כדי לשפר את קצב העברת הנתונים ואת ניצול המשאבים. אם בתהליך העבודה שלכם יש יותר מ-20 חיבורים בו-זמנית, מומלץ להשתמש בריבוב. ריבוב זמין ב-Java וב-Go. פרטים על הטמעה ב-Java מופיעים במאמר שימוש בריבוב. פרטים על הטמעה ב-Go זמינים במאמר בנושא שיתוף חיבורים (multiplexing). אם משתמשים במחבר Beam עם סמנטיקה של 'לפחות פעם אחת', אפשר להפעיל מולטיפלקסינג באמצעות UseStorageApiConnectionPool. מחבר Dataproc Spark מופעל כברירת מחדל עם Multiplexing.
כדי להשיג את הביצועים הטובים ביותר, מומלץ להשתמש בחיבור אחד לכמה שיותר פעולות כתיבה של נתונים. אל תשתמשו בחיבור אחד רק לכתיבה אחת, או אל תפתחו ותסגרו זרמים לכתיבות קטנות רבות.
יש מכסה על מספר החיבורים בו-זמנית שאפשר לפתוח בו-זמנית לכל פרויקט. אם חורגים מהמגבלה, הקריאות אל AppendRows נכשלות.
עם זאת, אפשר להגדיל את המכסה של חיבורים בו-זמניים, ובדרך כלל היא לא מהווה גורם מגביל להרחבת היקף הפעילות.
כל קריאה ל-AppendRows יוצרת אובייקט חדש של כתיבת נתונים. לכן, כשמשתמשים בעדכון תוכן שנוצר על ידי אפליקציה, מספר החיבורים תואם למספר עדכוני התוכן שנוצרו. בדרך כלל, חיבור יחיד תומך ברוחב פס של לפחות 1 MBps. הגבול העליון תלוי בכמה גורמים, כמו רוחב הפס של הרשת, הסכימה של הנתונים ועומס השרת, אבל יכול להיות גבוה מ-10MBps.
יש גם מכסה על התפוקה הכוללת לכל פרויקט. הערך הזה מייצג את מספר הבייטים בשנייה בכל החיבורים שמועברים דרך שירות Storage Write API. אם הפרויקט חורג מהמכסה הזו, אפשר לבקש לשנות את המכסה. בדרך כלל זה כולל הגדלה של מכסות נלוות, כמו מכסת החיבורים בו-זמנית, ביחס שווה.
ניהול היסטים של שידורים כדי להשיג סמנטיקה של 'פעם אחת בדיוק'
ממשק Storage Write API מאפשר כתיבה רק לסוף הנוכחי של הזרם, שמשתנה ככל שמוסיפים נתונים. המיקום הנוכחי בזרם מצוין כהיסט מתחילת הזרם.
כשכותבים לזרם שנוצר על ידי אפליקציה, אפשר לציין את ההיסט של הזרם כדי להשיג סמנטיקה של כתיבה בדיוק פעם אחת.
כשמציינים היסט, פעולת הכתיבה היא אידמפוטנטית, ולכן אפשר לנסות אותה שוב בבטחה אם יש שגיאות בחיבור לרשת או אם השרת לא מגיב. צריך לטפל בשגיאות הבאות שקשורות להיסטים:
-
ALREADY_EXISTS(StorageErrorCode.OFFSET_ALREADY_EXISTS): השורה כבר נכתבה. אפשר להתעלם מהשגיאה הזו. -
OUT_OF_RANGE (StorageErrorCode.OFFSET_OUT_OF_RANGE): פעולת כתיבה קודמת נכשלה. מנסים שוב מהכתיבה האחרונה שהצליחה.
חשוב לזכור שהשגיאות האלה יכולות לקרות גם אם מגדירים ערך שגוי של היסט, ולכן צריך לנהל את ההיסטים בזהירות.
לפני שמשתמשים בהיסטים של זרם, כדאי לשקול אם נדרשת סמנטיקה של בדיוק פעם אחת. לדוגמה, אם פייפליין הנתונים שלכם במעלה הזרם מבטיח רק כתיבה לפחות פעם אחת, או אם אתם יכולים לזהות בקלות כפילויות אחרי הטמעת נתונים, יכול להיות שלא תצטרכו כתיבה בדיוק פעם אחת. במקרה כזה, מומלץ להשתמש בזרם ברירת המחדל, שלא דורש מעקב אחרי היסט השורות.
לא לחסום שיחות ב-AppendRows
השיטה AppendRows היא אסינכרונית. אתם יכולים לשלוח סדרה של פעולות כתיבה בלי לחכות לתגובה לכל פעולת כתיבה בנפרד. הודעות התגובה בחיבור הדו-כיווני מגיעות באותו סדר שבו הבקשות הוכנסו לתור.
כדי להשיג את התפוקה הגבוהה ביותר, צריך להתקשר אל AppendRows בלי לחסום את ההמתנה לתגובה.
טיפול בעדכוני סכימה
בתרחישים של סטרימינג נתונים, סכימות של טבלאות מנוהלות בדרך כלל מחוץ לצינור הסטרימינג. מקובל שהסכימה תתפתח עם הזמן, למשל על ידי הוספה של שדות חדשים שניתן להשאיר ריקים. צינור נתונים חזק צריך לטפל בעדכוני סכימה מחוץ לפס.
Storage Write API תומך בסכימות של טבלאות באופן הבא:
- בקשת הכתיבה הראשונה כוללת את הסכימה.
- כל שורת נתונים נשלחת כמאגר אחסון לפרוטוקולים בינארי. BigQuery ממפה את הנתונים לסכימה.
- אפשר להשמיט שדות שניתן להגדיר בהם ערך null, אבל אי אפשר לכלול שדות שלא קיימים בסכימה הנוכחית. אם שולחים שורות עם שדות נוספים, Storage Write API מחזיר
StorageErrorעםStorageErrorCode.SCHEMA_MISMATCH_EXTRA_FIELD.
אם רוצים לשלוח שדות חדשים במטען הייעודי (payload), צריך קודם לעדכן את סכימת הטבלה ב-BigQuery. ממשק Storage Write API מזהה שינויים בסכימה אחרי זמן קצר, בסדר גודל של דקות. כש-Storage Write API מזהה את השינוי בסכימה, הודעת התגובה AppendRowsResponse מכילה אובייקט TableSchema שמתאר את הסכימה החדשה.
כדי לשלוח נתונים באמצעות הסכימה המעודכנת, צריך לסגור חיבורים קיימים ולפתוח חיבורים חדשים עם הסכימה החדשה.
Java client. ספריית הלקוח של Java מספקת כמה תכונות נוספות לעדכוני סכימה, באמצעות המחלקה JsonStreamWriter. אחרי עדכון סכימה, JsonStreamWriter מתחבר מחדש באופן אוטומטי עם הסכימה המעודכנת. אין צורך לסגור את החיבור ולפתוח אותו מחדש באופן מפורש.
כדי לבדוק שינויים בסכימה באופן פרוגרמטי, צריך להתקשר אל
AppendRowsResponse.hasUpdatedSchema אחרי שהשיטה append
מסיימת את הפעולה.
אפשר גם להגדיר את JsonStreamWriter להתעלם משדות לא מוכרים בנתוני הקלט. כדי להגדיר את ההתנהגות הזו, קוראים ל-setIgnoreUnknownFields. ההתנהגות הזו דומה לאפשרות ignoreUnknownValues כשמשתמשים בגרסה הקודמת של tabledata.insertAll API. עם זאת, היא עלולה לגרום לאובדן נתונים לא מכוון, כי שדות לא מוכרים מושמטים בלי התראה.