פונקציות בהגדרת המשתמש (UDF)

פונקציות בהגדרת המשתמש (UDF) ב-BigQuery מאפשרות להכיל לוגיקה עסקית מותאמת אישית באמצעות ביטויי SQL או קוד JavaScript. הגדרת פונקציות זמניות או קבועות משלכם מאפשרת לכם להרחיב את היכולות של BigQuery ולהשתמש שוב בחישובים מורכבים בכמה שאילתות.

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

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

פונקציות SQL מוגדרות על ידי המשתמש (UDF)

בדוגמה הבאה נוצרת פונקציית SQL UDF זמנית בשם AddFourAndDivide, והיא נקראת מתוך הצהרת SELECT:

CREATE TEMP FUNCTION AddFourAndDivide(x INT64, y INT64)
RETURNS FLOAT64
AS (
  (x + 4) / y
);

SELECT
  val, AddFourAndDivide(val, 2)
FROM
  UNNEST([2,3,5,8]) AS val;

הפלט של הדוגמה הזו:

+-----+-----+
| val | f0_ |
+-----+-----+
|   2 | 3.0 |
|   3 | 3.5 |
|   5 | 4.5 |
|   8 | 6.0 |
+-----+-----+

בדוגמה הבאה נוצרת אותה פונקציה כפונקציה מתמידה:

CREATE FUNCTION mydataset.AddFourAndDivide(x INT64, y INT64)
RETURNS FLOAT64
AS (
  (x + 4) / y
);

מכיוון שה-UDF הזו היא מתמידה, צריך לציין קבוצת נתונים לפונקציה (mydataset בדוגמה הזו). אחרי שמריצים את ההצהרה CREATE FUNCTION, אפשר לקרוא לפונקציה משאילתה:

SELECT
  val, mydataset.AddFourAndDivide(val, 2)
FROM
  UNNEST([2,3,5,8,12]) AS val;

פרמטרים של תבניות SQL UDF

פרמטר עם סוג ששווה ל-ANY TYPE יכול להתאים ליותר מסוג ארגומנט אחד כשקוראים לפונקציה.

  • אם ליותר מפרמטר אחד יש את הסוג ANY TYPE, ‏BigQuery לא אוכף קשר בין הסוגים של הארגומנטים האלה.
  • סוג ההחזרה של הפונקציה לא יכול להיות ANY TYPE. צריך להשמיט אותו, כלומר הוא ייקבע באופן אוטומטי על סמך sql_expression, או שהוא צריך להיות סוג מפורש.
  • אם תעבירו לפונקציה ארגומנטים מסוגים שלא תואמים להגדרה של הפונקציה, תתקבל שגיאה בזמן הקריאה.

בדוגמה הבאה מוצגת פונקציית SQL UDF שמשתמשת בפרמטר עם תבנית.

CREATE TEMP FUNCTION addFourAndDivideAny(x ANY TYPE, y ANY TYPE)
AS (
  (x + 4) / y
);

SELECT
  addFourAndDivideAny(3, 4) AS integer_input,
  addFourAndDivideAny(1.59, 3.14) AS floating_point_input;

הפלט של הדוגמה הזו:

+----------------+-----------------------+
| integer_input  |  floating_point_input |
+----------------+-----------------------+
| 1.75           | 1.7802547770700636    |
+----------------+-----------------------+

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

CREATE TEMP FUNCTION lastArrayElement(arr ANY TYPE)
AS (
  arr[ORDINAL(ARRAY_LENGTH(arr))]
);

SELECT
  lastArrayElement(x) AS last_element
FROM (
  SELECT [2,3,5,8,13] AS x
);

הפלט של הדוגמה הזו:

+--------------+
| last_element |
+--------------+
| 13           |
+--------------+

שאילתות משנה סקלריות

פונקציית SQL UDF יכולה להחזיר את הערך של שאילתת משנה סקלרית. שאילתת משנה סקלרית חייבת לבחור עמודה אחת.

בדוגמה הבאה מוצגת פונקציית SQL UDF שמשתמשת בשאילתת משנה סקלרית כדי לספור את מספר המשתמשים בגיל מסוים בטבלת משתמשים:

CREATE TEMP TABLE users
AS (
  SELECT
    1 AS id, 10 AS age
  UNION ALL
  SELECT
    2 AS id, 30 AS age
  UNION ALL
  SELECT
    3 AS id, 10 AS age
);

CREATE TEMP FUNCTION countUserByAge(userAge INT64)
AS (
  (SELECT COUNT(1) FROM users WHERE age = userAge)
);

SELECT
  countUserByAge(10) AS count_user_age_10,
  countUserByAge(20) AS count_user_age_20,
  countUserByAge(30) AS count_user_age_30;

הפלט של הדוגמה הזו:

+-------------------+-------------------+-------------------+
| count_user_age_10 | count_user_age_20 | count_user_age_30 |
+-------------------+-------------------+-------------------+
|                 2 |                 0 |                 1 |
+-------------------+-------------------+-------------------+

פרויקט ברירת המחדל בביטויי SQL

בגוף של פונקציית SQL UDF, כל ההפניות לישויות של BigQuery, כמו טבלאות או תצוגות, חייבות לכלול את מזהה הפרויקט, אלא אם הישות נמצאת באותו פרויקט שמכיל את פונקציית ה-UDF.

לדוגמה, נניח שאתם רוצים להשתמש בהצהרה הבאה:

CREATE FUNCTION project1.mydataset.myfunction()
AS (
  (SELECT COUNT(*) FROM mydataset.mytable)
);

אם מריצים את ההצהרה הזו מ-project1 ו-mydataset.mytable קיים ב-project1, ההצהרה תצליח. אבל אם תריצו את ההצהרה הזו מפרויקט אחר, היא תיכשל. כדי לתקן את השגיאה, צריך לכלול את מזהה הפרויקט בהפניה לטבלה:

CREATE FUNCTION project1.mydataset.myfunction()
AS (
  (SELECT COUNT(*) FROM project1.mydataset.mytable)
);

אפשר גם להפנות לישות בפרויקט או במערך נתונים אחרים, ולא רק לזה שבו יוצרים את הפונקציה:

CREATE FUNCTION project1.mydataset.myfunction()
AS (
  (SELECT COUNT(*) FROM project2.another_dataset.another_table)
);

שימוש במשתני מערכת עם פונקציות SQL UDF

משתני המערכת @@session_id ו-@@location נתמכים בפונקציות SQL UDF. אתם יכולים לכלול את משתני המערכת האלה בכל מקום בהצהרה ליצירת הפונקציה, כדי להחזיר את מזהה הסשן או את המיקום של השאילתה הנוכחית. אין תמיכה במשתני מערכת אחרים.

פונקציות JavaScript מוגדרות על ידי המשתמש (UDF)

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

בדוגמה הבאה מוצגת פונקציית UDF ב-JavaScript. קוד ה-JavaScript מופיע במירכאות בתוך מחרוזת גולמית.

CREATE TEMP FUNCTION multiplyInputs(x FLOAT64, y FLOAT64)
RETURNS FLOAT64
LANGUAGE js
AS r"""
  return x*y;
""";

WITH numbers AS
  (SELECT 1 AS x, 5 as y
  UNION ALL
  SELECT 2 AS x, 10 as y
  UNION ALL
  SELECT 3 as x, 15 as y)
SELECT x, y, multiplyInputs(x, y) AS product
FROM numbers;

הפלט של הדוגמה הזו:

+-----+-----+--------------+
| x   | y   | product      |
+-----+-----+--------------+
| 1   | 5   | 5            |
| 2   | 10  | 20           |
| 3   | 15  | 45           |
+-----+-----+--------------+

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

CREATE TEMP FUNCTION SumFieldsNamedFoo(json_row STRING)
RETURNS FLOAT64
LANGUAGE js
AS r"""
  function SumFoo(obj) {
    var sum = 0;
    for (var field in obj) {
      if (obj.hasOwnProperty(field) && obj[field] != null) {
        if (typeof obj[field] == "object") {
          sum += SumFoo(obj[field]);
        } else if (field == "foo") {
          sum += obj[field];
        }
      }
    }
    return sum;
  }
  var row = JSON.parse(json_row);
  return SumFoo(row);
""";

WITH Input AS (
  SELECT
    STRUCT(1 AS foo, 2 AS bar, STRUCT('foo' AS x, 3.14 AS foo) AS baz) AS s,
    10 AS foo
  UNION ALL
  SELECT
    NULL,
    4 AS foo
  UNION ALL
  SELECT
    STRUCT(NULL, 2 AS bar, STRUCT('fizz' AS x, 1.59 AS foo) AS baz) AS s,
    NULL AS foo
)
SELECT
  TO_JSON_STRING(t) AS json_row,
  SumFieldsNamedFoo(TO_JSON_STRING(t)) AS foo_sum
FROM Input AS t;

הפלט שמתקבל מהדוגמה:

+---------------------------------------------------------------------+---------+
| json_row                                                            | foo_sum |
+---------------------------------------------------------------------+---------+
| {"s":{"foo":1,"bar":2,"baz":{"x":"foo","foo":3.14}},"foo":10}       | 14.14   |
| {"s":null,"foo":4}                                                  | 4       |
| {"s":{"foo":null,"bar":2,"baz":{"x":"fizz","foo":1.59}},"foo":null} | 1.59    |
+---------------------------------------------------------------------+---------+

סוגי נתונים נתמכים של פונקציות JavaScript בהגדרת משתמש

לחלק מסוגי ה-SQL יש מיפוי ישיר לסוגי JavaScript, אבל לאחרים אין. ב-BigQuery, הסוגים מיוצגים באופן הבא:

סוג הנתונים ב-BigQuery סוג הנתונים ב-JavaScript
ARRAY ARRAY
BOOL בוליאני
BYTES מחרוזת בקידוד Base64
FLOAT64 מספר
NUMERIC, ‏ BIGNUMERIC אם אפשר לייצג ערך NUMERIC או BIGNUMERIC בדיוק כערך נקודה צפה (floating-point) של IEEE 754 ואין לו חלק של שבר, הערך מקודד כ-Number. הערכים האלה הם בטווח [‎-253, 253]. אחרת, הערך מקודד כמחרוזת.
מחרוזת מחרוזת
STRUCT ‫OBJECT שבו כל שדה STRUCT הוא שדה בעל שם
TIMESTAMP DATE עם שדה מיקרו-שנייה שמכיל את החלק microsecond של חותמת הזמן
תאריך תאריך
JSON

אובייקטים, מערכים וערכים ב-JSON מומרים לאובייקטים, מערכים וערכים מקבילים ב-JavaScript.

‫JavaScript לא תומך בערכי INT64. רק מספרי JSON בטווח [‎-253, 253] מומרים באופן מדויק. אחרת, הערך המספרי מעוגל, מה שעלול לגרום לאובדן הדיוק.

מכיוון ש-JavaScript לא תומך בסוג של מספר שלם של 64 ביט, INT64 לא נתמך כסוג קלט לפונקציות UDF של JavaScript. במקום זאת, השתמשו ב-FLOAT64 כדי לייצג ערכים של מספרים שלמים כמספר, או ב-STRING כדי לייצג ערכים של מספרים שלמים כמחרוזת.

‫BigQuery תומך ב-INT64 כסוג החזרה בפונקציות UDF של JavaScript. במקרה כזה, גוף הפונקציה של JavaScript יכול להחזיר מספר או מחרוזת של JavaScript. לאחר מכן, BigQuery ממיר את אחד מהסוגים האלה ל-INT64.

אם ערך ההחזרה של פונקציית ה-UDF ב-JavaScript הוא Promise, המערכת של BigQuery ממתינה ל-Promise עד ש-Promise מוסדר. אם ה-Promise עובר למצב fulfilled, ‏ BigQuery מחזיר את התוצאה שלו. אם ה-Promise נדחה, BigQuery מחזיר שגיאה.

כללי ציטוטים

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

CREATE TEMP FUNCTION plusOne(x FLOAT64)
RETURNS FLOAT64
LANGUAGE js
AS "return x+1;";

SELECT val, plusOne(val) AS result
FROM UNNEST([1, 2, 3, 4, 5]) AS val;

הפלט של הדוגמה הזו:

+-----------+-----------+
| val       | result    |
+-----------+-----------+
| 1         | 2.0       |
| 2         | 3.0       |
| 3         | 4.0       |
| 4         | 5.0       |
| 5         | 6.0       |
+-----------+-----------+

אם קטע הקוד מכיל מירכאות או מורכב מכמה שורות, משתמשים בבלוקים עם מירכאות משולשות:

CREATE TEMP FUNCTION customGreeting(a STRING)
RETURNS STRING
LANGUAGE js
AS r"""
  var d = new Date();
  if (d.getHours() < 12) {
    return 'Good Morning, ' + a + '!';
  } else {
    return 'Good Evening, ' + a + '!';
  }
""";

SELECT customGreeting(names) AS everyone
FROM UNNEST(['Hannah', 'Max', 'Jakob']) AS names;

הפלט של הדוגמה הזו:

+-----------------------+
| everyone              |
+-----------------------+
| Good Morning, Hannah! |
| Good Morning, Max!    |
| Good Morning, Jakob!  |
+-----------------------+

הוספת ספריות JavaScript

אפשר להרחיב את פונקציות ה-UDF ב-JavaScript באמצעות הקטע OPTIONS. בקטע הזה אפשר לציין ספריות קוד חיצוניות ל-UDF.

CREATE TEMP FUNCTION myFunc(a FLOAT64, b STRING)
RETURNS STRING
LANGUAGE js
  OPTIONS (
    library=['gs://my-bucket/path/to/lib1.js', 'gs://my-bucket/path/to/lib2.js'])
AS r"""
  // Assumes 'doInterestingStuff' is defined in one of the library files.
  return doInterestingStuff(a, b);
""";

SELECT myFunc(3.14, 'foo');

בדוגמה שלמעלה, הקוד ב-lib1.js וב-lib2.js זמין לכל קוד בקטע [external_code] של ה-UDF.

שיטות מומלצות לפונקציות UDF ב-JavaScript

סינון מראש של הקלט

אם אפשר לסנן את הקלט לפני שהוא מועבר לפונקציית UDF ב-JavaScript, יכול להיות שהשאילתה תהיה מהירה וזולה יותר.

הימנעות ממצב קבוע שניתן לשינוי

אל תאחסנו מצב שניתן לשינוי בקריאות JavaScript UDF ואל תיגשו אליו. לדוגמה, הימנעו מהתבנית הבאה:

-- Avoid this pattern
CREATE FUNCTION temp.mutable()
RETURNS INT64
LANGUAGE js
AS r"""
  var i = 0; // Mutable state
  function dontDoThis() {
    return ++i;
  }
  return dontDoThis()
""";

שימוש יעיל בזיכרון

לסביבת העיבוד של JavaScript יש זיכרון מוגבל לכל שאילתה. שאילתות UDF ב-JavaScript שצוברות יותר מדי מצב מקומי עלולות להיכשל בגלל מחסור בזיכרון.

אישור תרחישים

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

הוספת תיאורים לפונקציות מוגדרות על ידי המשתמש (UDF)

כדי להוסיף תיאור לפונקציה מוגדרת-משתמש:

המסוף

  1. נכנסים לדף BigQuery במסוף Google Cloud .

    כניסה ל-BigQuery

  2. בחלונית הימנית, לוחצים על Explorer:

    כפתור מודגש לחלונית Explorer.

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

  3. בחלונית Explorer, מרחיבים את הפרויקט ולוחצים על Datasets.

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

  5. לוחצים על הכרטיסייה פונקציות ובוחרים את הפונקציה.

  6. בחלונית הפרטים, לוחצים על Edit Routine Details כדי לערוך את טקסט התיאור.

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

SQL

כדי לעדכן את התיאור של פונקציה, יוצרים אותה מחדש באמצעות הצהרת ה-DDL‏ CREATE FUNCTION ומגדירים את השדה description ברשימה OPTIONS:

  1. נכנסים לדף BigQuery במסוף Google Cloud .

    כניסה ל-BigQuery

  2. בעורך השאילתות, מזינים את ההצהרה הבאה:

    CREATE OR REPLACE FUNCTION mydataset.my_function(...)
    AS (
      ...
    ) OPTIONS (
      description = 'DESCRIPTION'
    );

  3. ‫לוחצים על Run.

מידע נוסף על הרצת שאילתות זמין במאמר הרצת שאילתה אינטראקטיבית.

יצירת תרחישים מותאמים אישית להסתרת רעשים

אתם יכולים ליצור פונקציות UDF לשימוש עם פונקציות מיסוך בהתאמה אישית. כדאי ליצור מערכי נתונים ייעודיים ולהגדיר הרשאות IAM מתאימות לניהול פונקציות UDF להסתרת מידע. שגרות מיסוך בהתאמה אישית צריכות לעמוד בדרישות הבאות:

  • שגרת המיסוך בהתאמה אישית חייבת להיות SQL UDF.
  • בפונקציה OPTIONS, צריך להגדיר את האפשרות data_governance_type לערך DATA_MASKING.
  • אפשר להשתמש בפונקציות הבאות בשגרות של הסתרת מידע בהתאמה אישית:
    • AEAD.DECRYPT_BYTES פונקציית הצפנה של AEAD עם KEYS.KEYSET_CHAIN (אין תמיכה בשימוש במפתח גולמי)
    • AEAD.DECRYPT_STRING פונקציית הצפנה של AEAD עם KEYS.KEYSET_CHAIN (אין תמיכה בשימוש במפתח גולמי)
    • פונקציית הצפנה מסוג AEAD.ENCRYPT AEAD עם keyset_chain (אין תמיכה בשימוש במפתח גולמי)
    • פונקציית ההמרה CAST
    • פונקציית המחרוזת CONCAT
    • CURRENT_DATETIME פונקציית datetime
    • פונקציית התאריך CURRENT_DATE
    • CURRENT_TIMESTAMP פונקציית חותמת הזמן
    • פונקציית הזמן CURRENT_TIME
    • DETERMINISTIC_DECRYPT_BYTES פונקציית הצפנה של AEAD עם KEYS.KEYSET_CHAIN (אין תמיכה בשימוש במפתח גולמי)
    • DETERMINISTIC_DECRYPT_STRING פונקציית הצפנה של AEAD עם KEYS.KEYSET_CHAIN (אין תמיכה בשימוש במפתח גולמי)
    • DETERMINISTIC_ENCRYPT פונקציית הצפנה של AEAD עם KEYS.KEYSET_CHAIN (אין תמיכה בשימוש במפתח גולמי)
    • FARM_FINGERPRINT פונקציית גיבוב (hash)
    • פונקציית המחרוזת FROM_BASE32
    • פונקציית המחרוזת FROM_BASE64
    • פונקציית המחרוזת FROM_HEX
    • GENERATE_UUID פונקציה בסיסית
    • פונקציית ההצפנה KEYS.KEYSET_CHAIN AEAD
    • פונקציית המחרוזת LENGTH
    • פונקציית המחרוזת LOWER
    • פונקציית המחרוזת LPAD
    • פונקציית המחרוזת LTRIM
    • MD5 פונקציית גיבוב (hash)
    • פונקציית המחרוזת REGEXP_REPLACE
    • פונקציית המחרוזת REGEXP_EXTRACT
    • פונקציית המחרוזת REPLACE
    • פונקציית המחרוזת RPAD
    • פונקציית המחרוזת RTRIM
    • פונקציית ההמרה SAFE_CAST
    • SHA1 פונקציית גיבוב (hash)
    • SHA256 פונקציית גיבוב (hash)
    • SHA512 פונקציית גיבוב (hash)
    • פונקציית המחרוזת STARTS_WITH
    • פונקציית המחרוזת SUBSTRING
    • פונקציית המחרוזת SUBSTR
    • פונקציית המחרוזת TO_BASE32
    • פונקציית המחרוזת TO_BASE64
    • פונקציית המחרוזת TO_HEX
    • פונקציית המחרוזת TRIM
    • פונקציית המחרוזת UPPER
  • שגרות מיסוך בהתאמה אישית יכולות לקבל קלט אחד או לא לקבל קלט בכלל בתוך סוגי הנתונים של BigQuery, חוץ מ-GEOGRAPHY ו-STRUCT. אי אפשר להשתמש ב-GEOGRAPHY וב-STRUCT בשגרות של הסתרת מידע בהתאמה אישית.
  • אין תמיכה בפרמטרים של תבניות SQL UDF.
  • כשמזינים קלט, סוגי הנתונים של הקלט והפלט חייבים להיות זהים.
  • צריך לציין סוג פלט.
  • אי אפשר להפנות לפונקציות UDF, לשאילתות משנה, לטבלאות או לתצוגות אחרות בגוף ההגדרה.
  • אחרי שיוצרים שגרת מיסוך, אי אפשר לשנות אותה לפונקציה רגילה. כלומר, אם האפשרות data_governance_type מוגדרת ל-DATA_MASKING, אי אפשר לשנות את data_governance_type באמצעות הצהרות DDL או קריאות ל-API.
  • שגרות מיסוך בהתאמה אישית תומכות בהצהרות CASE ו-CASE expr. אפשר להשתמש באופרטורים הבאים עם הצהרות CASE ו-CASE expr:

לדוגמה, שגרת הסתרה שמחליפה את מספר תעודת הזהות של המשתמש ב-XXX-XX-XXXX עשויה להיראות כך:

  CREATE OR REPLACE FUNCTION SSN_Mask(ssn STRING) RETURNS STRING
  OPTIONS (data_governance_type="DATA_MASKING") AS (
  SAFE.REGEXP_REPLACE(ssn, '[0-9]', 'X') # 123-45-6789 -> XXX-XX-XXXX
  );

בדוגמה הבאה מתבצע גיבוב (hash) עם salt שסופק על ידי המשתמש, באמצעות הפונקציה SHA256:

CREATE OR REPLACE FUNCTION `project.dataset.masking_routine1`(
  ssn STRING)
RETURNS STRING OPTIONS (data_governance_type = 'DATA_MASKING')
AS (
  CAST(SHA256(CONCAT(ssn, 'salt')) AS STRING format 'HEX')
);

בדוגמה הבאה, עמודה מסוג DATETIME מוסתרת באמצעות ערך קבוע:

CREATE OR REPLACE FUNCTION `project.dataset.masking_routine2`(
  column DATETIME)
RETURNS DATETIME OPTIONS (data_governance_type = 'DATA_MASKING')
AS (
  SAFE_CAST('2023-09-07' AS DATETIME)
);

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

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

פונקציות שהקהילה תרמה

פונקציות UDF שנוספו על ידי הקהילה זמינות במערך הנתונים הציבורי bigquery-public-data.persistent_udfs ובמאגר הקוד הפתוח bigquery-utils ב-GitHub. כדי לראות את כל הפונקציות המוגדרות על ידי המשתמש (UDF) של הקהילה במסוף Google Cloud , מסמנים בכוכב את הפרויקט bigquery-public-data בחלונית Explorer ואז מרחיבים את קבוצת הנתונים המקוננת persistent_udfs בתוך הפרויקט.

מתן גישה לפונקציות שנוספו על ידי הקהילה בהיקף של VPC Service Controls

בפרויקטים שבהם מופעל VPC Service Controls ו-BigQuery הוא שירות מוגן, צריך להגדיר כלל לתעבורת נתונים יוצאת (egress) לפרויקט bigquery-public-data (מזהה הפרויקט: 1057666841514).

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

  • bigquery.routines.get (לשימוש בתרחישים)
  • bigquery.tables.getData (לשליחת שאילתות לטבלאות ב-BigQuery)

הקוד הבא מציג דוגמה להגדרת YAML:

  - egressFrom:
      identityType: ANY_IDENTITY
    egressTo:
      operations:
      - serviceName: 'bigquery.googleapis.com'
        methodSelectors:
        - permission: 'bigquery.routines.get'
        - permission: 'bigquery.tables.getData'
      resources:
      - projects/1057666841514 # bigquery-public-data

אם אתם רוצים לתרום לפונקציות ה-UDF במאגר הזה, קראו את ההוראות במאמר תרומה לפונקציות UDF.

גישה מאוחדת לפונקציות בכמה אזורים

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

שאילתה במספר אזורים ב-EU:

  SELECT
    id,
    europe_dataset.my_function(value)
  FROM
    sales;

שאילתה במספר אזורים ב-US:

  SELECT
    id,
    us_dataset.my_function(value)
  FROM
    sales;

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

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

  1. יוצרים קבוצת נתונים ייעודית חדשה, לדוגמה my_utils, כדי לאחסן את כל ה-UDF הנדרשים. חשוב לזכור שכל הטבלאות שנוספות למערך הנתונים הזה ישוכפלו, מה שיגדיל את העלות. עם זאת, שכפול של פונקציות UDF ופרוצדורות לא כרוך בעלות נוספת.
  2. מוסיפים את כל ה-UDF שלכם לקבוצת הנתונים החדשה. זה יכול לכלול גם פונקציות UDF של הקהילה, כמו bqutil שהועתקו מ-GitHub.
  3. הפעלת שכפול של מערך נתונים. מגדירים את מערך הנתונים הזה כך שישוכפל לכל האזורים שבהם צריך להריץ שאילתות שקוראות לפונקציות ה-UDF האלה. הפעולה הזו תעתיק את הפונקציות לאזורים האלה ותסנכרן אותן.

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

  SELECT
    id,
    my_utils.my_function(value)
  FROM
    sales;

מגבלות

המגבלות הבאות חלות על פונקציות זמניות ופונקציות מתמידות בהגדרת המשתמש:

  • אין תמיכה באובייקטים של DOM‏ Window,‏ Document ו-Node, ובפונקציות שדורשות אותם.
  • פונקציות JavaScript פועלות בסביבת ארגז חול, ופונקציות שמסתמכות על קוד מערכת בסיסי עלולות להיכשל בגלל קריאות מערכת מוגבלות.
  • יכול להיות שפונקציית UDF ב-JavaScript תגרום לזמן קצוב לתפוגה ותמנע את השלמת השאילתה. זמן קצוב לתפוגה יכול להיות קצר כמו 5 דקות, אבל הוא יכול להשתנות בהתאם לכמה גורמים, כולל כמה זמן מעבד (CPU) של המשתמש הפונקציה צורכת, וכמה גדולים הקלט והפלט של פונקציית ה-JavaScript.
  • פעולות Bitwise ב-JavaScript מטפלות רק ב-32 הביטים המשמעותיים ביותר.
  • פונקציות UDF כפופות למגבלות מסוימות של הגבלת קצב של יצירת בקשות ומכסות. מידע נוסף זמין במאמר מגבלות של פונקציות UDF.

המגבלות הבאות חלות על פונקציות מתמידות בהגדרת המשתמש:

  • כל קבוצת נתונים יכולה להכיל רק פונקציה מתמידה אחת עם אותו שם. עם זאת, אפשר ליצור פונקציה מוגדרת-משתמש עם שם זהה לשם של טבלה באותה קבוצת נתונים.
  • כשמפנים לפונקציה מתמידה מוגדרת-משתמש מפונקציה מתמידה מוגדרת-משתמש אחרת או מתצוגה לוגית, צריך להוסיף לשם את קבוצת הנתונים. לדוגמה:
    CREATE FUNCTION mydataset.referringFunction() AS (mydataset.referencedFunction());
  • אפשר להפעיל פונקציות מתמידות בבטחה כשמשתפים אותן בין בעלים. פונקציות UDF לא יכולות לשנות נתונים, לתקשר עם מערכות חיצוניות או לשלוח יומנים ל-Google Cloud Observability או לאפליקציות דומות.

המגבלות הבאות חלות על פונקציות זמניות בהגדרת המשתמש.

  • כשיוצרים פונקציית UDF זמנית, function_name לא יכול להכיל נקודות.
  • תצוגות ופונקציות UDF מתמידות לא יכולות להפנות לפונקציות UDF זמניות.