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

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

שימוש במצב הזמנה חלקית

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

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

מצב סדר חלקי מונע מ-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().

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

פתרון בעיות

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

שגיאה: חובה להזין הזמנה

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

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

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

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

שגיאת אינדקס ריק

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

כשמשתמשים בפעולה שדורשת אינדקס עם מצב סדר חלקי, הפעולה מעלה הודעת 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, הפעולות נשמרות באופן מקומי והרצת השאילתות נדחית עד שמתקיימים תנאים מסוימים. זה יכול לגרום לאותן פעולות לפעול כמה פעמים בשאילתות שונות.

כדי להימנע מחזרה על פעולות יקרות, שמרו תוצאות ביניים באמצעות ה-method‏ 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 באמצעות notebooks או מנפה השגיאות של ה-IDE. הקריאה הזו מפעילה את הקריאה ל-head(), שמאחזרת את הנתונים בפועל. השליפה הזו יכולה להאט את תהליך הקידוד וניפוי הבאגים, וגם לגרום לעלויות.

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

import bigframes.pandas as bpd

bpd.options.display.repr_mode = "deferred"

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

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