אופטימיזציה של הביצועים של BigQuery DataFrames

בעזרת BigQuery DataFrames אפשר לנתח ולשנות נתונים ב-BigQuery באמצעות ממשק API שתואם ל-pandas. כדי לעבד את הנתונים מהר יותר ובצורה חסכונית יותר, אפשר להשתמש בכמה טכניקות לשיפור הביצועים.

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

שימוש במצב של סדר חלקי

ל-BigQuery DataFrames יש תכונה של מצב סידור, שמכתיבה סדר שורות ספציפי לפעולות כמו פונקציות חלון וצירופים. אפשר לציין את מצב ההזמנה על ידי הגדרת המאפיין ordering_mode לערך strict (שנקרא מצב הזמנה מחמיר, שהוא ברירת המחדל) או לערך partial (שנקרא מצב הזמנה חלקי). השימוש בהגדרה partial יכול לשפר את היעילות של השאילתות.

מצב הזמנה חלקי שונה ממצב הזמנה מדויק. במצב 'סדר קפדני' כל השורות מסודרות בסדר מסוים. הסדר הכולל הזה משפר את העבודה עם BigQuery DataFrames באמצעות pandas, ומאפשר לכם לגשת לשורות לפי הסדר שלהן באמצעות המאפיין DataFrame.iloc. עם זאת, המיון הכולל והאינדקס הרציף שמוגדר כברירת מחדל מונעים ממסננים בעמודות או בשורות לצמצם את כמות הנתונים שנסרקים. הסינון הזה מתבצע אלא אם אתם משתמשים במסננים האלה כפרמטרים בפונקציות read_gbq ו-read_gbq_table. כדי למיין את כל השורות ב-DataFrame, ‏ BigQuery DataFrames יוצר גיבוב של כל השורות. הפעולה הזו עלולה לגרום לסריקת נתונים מלאה שמתעלמת ממסנני שורות ועמודות.

מצב הזמנה חלקית מונע מ-BigQuery DataFrames ליצור סדר כולל לכל השורות, ומשבית תכונות שדורשות סדר כולל, כמו המאפיין DataFrame.iloc. במצב של סידור חלקי, המחלקה DefaultIndexKind מוגדרת לאינדקס null, במקום לאינדקס רציף.

כשמסננים אובייקט DataFrame באמצעות מצב של סדר חלקי, BigQuery DataFrames לא מחשב אילו שורות חסרות באינדקס הרציף. בנוסף, במצב של סדר חלקי, הנתונים לא משולבים אוטומטית על סמך האינדקס. הגישות האלה יכולות לשפר את היעילות של השאילתות. עם זאת, בין אם משתמשים במצב ברירת המחדל של סדר קפדני או במצב של סדר חלקי, BigQuery DataFrames API פועל כמו pandas API המוכר.

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

הפעלת מצב הזמנה חלקית

כדי להשתמש בסדר חלקי, צריך להגדיר את המאפיין ordering_mode לערך partial לפני שמבצעים פעולות אחרות עם BigQuery DataFrames, כמו שמוצג בדוגמת הקוד הבאה:

import bigframes.pandas as bpd

bpd.options.bigquery.ordering_mode = "partial"

מצב סידור חלקי מונע הצטרפות מרומזת של אובייקטים לא קשורים של BigQuery DataFrames כי אין להם אינדקס רציף. במקום זאת, צריך לקרוא באופן מפורש לשיטה DataFrame.merge כדי לצרף שני אובייקטים של BigQuery DataFrames שמקורם בביטויי טבלה שונים.

התכונות Series.unique() ו-Series.drop_duplicates() לא פועלות במצב של הזמנה חלקית. במקום זאת, משתמשים בשיטה groupby כדי למצוא ערכים ייחודיים, כמו בדוגמה הבאה:

# Avoid order dependency by using groupby instead of drop_duplicates.
unique_col = df.groupby(["column"], as_index=False).size().drop(columns="size")

במצב של סדר חלקי, יכול להיות שהפלט של הפונקציות DataFrame.head(n) ו-Series.head(n) לא יהיה זהה בכל הרצה. כדי להוריד דגימה קטנה ואקראית של הנתונים, משתמשים בשיטות DataFrame.peek() או Series.peek().

תוכלו לעיין במדריך מפורט שבו נעשה שימוש במאפיין ordering_mode = "partial" במאמר ניתוח הורדות של חבילות מ-PyPI באמצעות BigQuery DataFrames.

פתרון בעיות

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

שגיאה שנדרשת הזמנה

כדי להשתמש בחלק מהתכונות, כמו הפונקציות DataFrame.head() ו-DataFrame.iloc, צריך להגדיר סדר. רשימת התכונות שדורשות הזמנה מופיעה בעמודה Requires ordering (נדרשת הזמנה) במאמר ממשקי API נתמכים של pandas.

אם לא מוגדר סדר לאובייקט, הפעולה תיכשל ותוצג הודעה כמו הבאה: OrderRequiredErrorOrderRequiredError: Op iloc requires an ordering. Use .sort_values or .sort_index to provide an ordering.

כפי שמצוין בהודעת השגיאה, אפשר לספק הזמנה באמצעות השיטה DataFrame.sort_values() כדי למיין לפי עמודה אחת או יותר. שיטות אחרות, כמו DataFrame.groupby(), מספקות באופן מרומז סדר כולל על סמך המפתחות של הקיבוץ לפי.

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

שגיאה באינדקס Null

כדי להשתמש בחלק מהתכונות, כמו המאפיינים DataFrame.unstack() ו-Series.interpolate(), צריך ליצור אינדקס. רשימת התכונות שמחייבות אינדקס מופיעה בעמודה Requires index בטבלה Supported pandas APIs.

כשמשתמשים בפעולה שמחייבת אינדקס עם מצב סדר חלקי, הפעולה מעלה הודעת NullIndexError כמו זו: NullIndexError: DataFrame cannot perform interpolate as it has no index. Set an index using set_index.

כפי שמצוין בהודעת השגיאה, אפשר לספק אינדקס באמצעות השיטה DataFrame.set_index() כדי למיין לפי עמודה אחת או יותר. שיטות אחרות, כמו DataFrame.groupby(), מספקות באופן מרומז אינדקס שמבוסס על המפתחות של הקיבוץ, אלא אם הפרמטר as_index=False מוגדר.

שמירת תוצאות במטמון אחרי פעולות יקרות

‫BigQuery DataFrames מאחסן פעולות באופן מקומי ודוחה את הרצת השאילתות עד שמתקיימים תנאים מסוימים. כתוצאה מכך, אותן פעולות יכולות לפעול כמה פעמים בשאילתות שונות.

כדי להימנע מחזרה על פעולות יקרות, כדאי לשמור תוצאות ביניים באמצעות המתודה cache(), כמו בדוגמה הבאה:

# Assume you have 3 large dataframes "users", "group" and "transactions"

# Expensive join operations
final_df = users.join(groups).join(transactions)
final_df.cache()
# Subsequent derived results will reuse the cached join
print(final_df.peek())
print(len(final_df[final_df["completed"]]))
print(final_df.groupby("group_id")["amount"].mean().peek(30))

בשיטה הזו נוצרת טבלה זמנית ב-BigQuery לאחסון התוצאות. החיוב על האחסון של הטבלה הזמנית הזו מתבצע ב-BigQuery.

תצוגה מקדימה של הנתונים באמצעות השיטה peek()

‫BigQuery DataFrames מציע שתי שיטות API לתצוגה מקדימה של נתונים:

  • peek(n) מחזירה n שורות של נתונים, כאשר n הוא מספר השורות.
  • head(n) מחזירה את n השורות הראשונות של הנתונים, בהתאם להקשר, כאשר n הוא מספר השורות.

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

import bigframes.pandas as bpd

# Read the "Penguins" table into a dataframe
df = bpd.read_gbq("bigquery-public-data.ml_datasets.penguins")

# Preview 3 random rows
df.peek(3)

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

דחיית אחזור הנתונים של repr()

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

כדי למנוע מהשיטה repr() לאחזר נתונים, מגדירים את המאפיין repr_mode לערך "deferred", כמו בדוגמה הבאה:

import bigframes.pandas as bpd

bpd.options.display.repr_mode = "deferred"

במצב ההשהיה, אפשר לראות תצוגה מקדימה של הנתונים רק באמצעות קריאות מפורשות של peek() ושל head().

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