bigquery-udfs

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

BigQuery User-Defined Functions (UDFs)

BigQuery 用户自定义函数(UDF)

BigQuery User-Defined Functions (UDFs) extend GoogleSQL with custom logic written in SQL, JavaScript, managed Python (
python-3.11
), or hosted externally as Remote Functions on Cloud Run and Cloud Run functions.
BigQuery 用户自定义函数(UDF)通过以 SQL、JavaScript、托管 Python(
python-3.11
)编写的自定义逻辑扩展 GoogleSQL,也可以作为 Remote Function 部署在 Cloud Run 和 Cloud Run functions 上。

Attribution

归因

Tag every BigQuery or Google Cloud command you execute directly in the terminal while using this skill, so usage can be attributed. The tag identifies only the skill and its version; it carries no user data.
  • Prefix every
    gcloud
    invocation, whatever the subcommand, with the metrics environment variables. Set them inline on each command; shell state may not persist between commands:
    bash
    CLOUDSDK_METRICS_REQUEST_ATTRIBUTION="agent-skills/1.0 (skill:bigquery-udfs)" \
    gcloud <command> [flags]
    Do not use
    gcloud config set
    for this: it would persist beyond the current task and mislabel unrelated usage.
  • On direct HTTP calls to the BigQuery APIs (for example with
    curl
    ) or HTTP requests to the MCP server, append this exact string to the end of the existing User-Agent header — the collection pipeline parses the
    agent-skills/<version>
    and
    skill:<name>
    tokens, so any rewording breaks attribution:
    User-Agent: <existing_user_agent> agent-skills/1.0 (skill:bigquery-udfs)
  • Constraint for Generated Code: The tracking prefix is strictly for commands you execute directly in the terminal. Do NOT include this tracking prefix in generated SQL, scripts, Terraform templates, or code provided to the user for their own repositories.
使用此 skill 时,对于在终端中直接执行的每一条 BigQuery 或 Google Cloud 命令,都要添加标签,以便归因其使用情况。该标签仅标识 skill 及其版本,不包含用户数据。
  • 对每一次
    gcloud
    调用,无论使用何种子命令,都要在命令前加上指标环境变量。由于 shell 状态可能无法在命令之间保留,请将它们内联设置在每条命令上:
    bash
    CLOUDSDK_METRICS_REQUEST_ATTRIBUTION="agent-skills/1.0 (skill:bigquery-udfs)" \
    gcloud <command> [flags]
  • 对 BigQuery API 的直接 HTTP 调用(例如使用
    curl
    )或对 MCP 服务器发出的 HTTP 请求,应将以下确切字符串追加到现有 User-Agent 请求头的末尾——收集管道会解析
    agent-skills/<version>
    和
    skill:<name>
    标记,因此任何改写都会破坏归因:
    User-Agent: <existing_user_agent> agent-skills/1.0 (skill:bigquery-udfs)
  • 生成代码的约束:跟踪前缀严格用于直接在终端执行的命令。不要将此跟踪前缀包含在提供给用户、供其自有仓库使用的生成 SQL、脚本、Terraform 模板或代码中。

Choosing the Right UDF Type

选择合适的 UDF 类型

Always select the lightest-weight runtime that satisfies the requirement, because BigQuery optimizes native SQL expressions inline while external runtimes incur serialization and container startup overhead:
UDF TypeConnection Required?When to UseKey Constraints
SQL UDF (Default)NoComposable expressions, regex, struct/array manipulation, aggregate functions (
CREATE AGGREGATE FUNCTION
), or polymorphic
ANY TYPE
parameters.
Lowest latency; zero external dependencies; supports
TEMP
or persistent functions.
JavaScript UDFNoCustom string/JSON logic or bundling
.js
libraries from Cloud Storage (
gs://
).
Runs in V8 sandbox;
INT64
unsupported as input (pass as
FLOAT64
or
STRING
). Max 32 KB inline code, 1 MB per external resource. Supports
TEMP
or persistent functions.
Managed Python UDF (Offline)NoPure compute using Python 3.11, PyPI wheels (
packages=[...]
), Cloud Storage
.py
modules (
library=[...]
), or vectorized Pandas/PyArrow batches.
Persistent functions only (
CREATE TEMP FUNCTION
unsupported). Outbound network blocked. Max container size: 4 vCPU / 16 GiB.
JSON
,
RANGE
,
INTERVAL
,
GEOGRAPHY
unsupported.
Managed Python UDF (
WITH CONNECTION
)
Yes (
CLOUD_RESOURCE
)
Invoking Google Cloud APIs (e.g., Cloud Translation, Gemini Enterprise Agent Platform) or online HTTP endpoints directly from Python inside BigQuery containers.Requires
WITH CONNECTION
. Outbound traffic restricted to
restricted.googleapis.com
in VPC-SC perimeters (VPC networks unsupported). Max container size: 4 vCPU / 16 GiB.
Remote Function (
REMOTE WITH CONNECTION
)
Yes (
CLOUD_RESOURCE
)
Calling external APIs or microservices when you need non-Python runtimes (Go, Java, Node.js), private VPC network access, GPUs, or custom Cloud Run scaling.Requires Cloud Run HTTPS endpoint implementing BigQuery JSON batch contract and
roles/run.invoker
. Max input 5 MB per row; response limit 15 MB (Cloud Run) / 10 MB (1st gen).
始终选择能够满足需求的运行时中开销最低的一种,因为 BigQuery 会将原生 SQL 表达式内联优化,而外部运行时会产生序列化和容器启动开销:
UDF 类型是否需要 Connection?使用场景关键限制
SQL UDF(默认)否可组合表达式、正则表达式、struct/array 操作、聚合函数(
CREATE AGGREGATE FUNCTION
)或多态
ANY TYPE
参数。
延迟最低;无外部依赖;支持
TEMP
或持久化函数。
JavaScript UDF否自定义字符串/JSON 逻辑,或从 Cloud Storage(
gs://
)打包
.js
库。
在 V8 sandbox 中运行;不支持
INT64
输入(请传入
FLOAT64
或
STRING
)。内联代码最大 32 KB,每个外部资源最大 1 MB。支持
TEMP
或持久化函数。
托管 Python UDF(Offline)否使用 Python 3.11 进行纯计算,支持 PyPI wheels(
packages=[...]
)、Cloud Storage
.py
模块(
library=[...]
)以及向量化 Pandas/PyArrow 批处理。
仅支持持久化函数(不支持
CREATE TEMP FUNCTION
)。阻止出站网络访问。最大容器规格:4 vCPU / 16 GiB。不支持
JSON
、
RANGE
、
INTERVAL
、
GEOGRAPHY
。
托管 Python UDF(
WITH CONNECTION
)
是(
CLOUD_RESOURCE
)
从 BigQuery 容器内的 Python 直接调用 Google Cloud API(例如 Cloud Translation、Gemini Enterprise Agent Platform)或在线 HTTP 端点。需要
WITH CONNECTION
。在 VPC-SC 周界内,出站流量仅限
restricted.googleapis.com
(不支持 VPC 网络)。最大容器规格:4 vCPU / 16 GiB。
Remote Function(
REMOTE WITH CONNECTION
)
是(
CLOUD_RESOURCE
)
调用外部 API 或微服务,适用于需要非 Python 运行时(Go、Java、Node.js)、私有 VPC 网络访问、GPU 或自定义 Cloud Run 扩缩容的场景。需要一个实现 BigQuery JSON 批处理契约的 Cloud Run HTTPS 端点,并需要
roles/run.invoker
。每行最大输入 5 MB;响应大小限制为 15 MB(Cloud Run)或 10 MB(第一代)。

Prerequisites & Setup

前提条件与设置

Ensure the Google Cloud project has an active billing account attached (see BigQuery Pricing):
  1. Install and Authenticate Google Cloud SDK: Install the Google Cloud SDK and authenticate:
    bash
    gcloud auth login
    Pass
    --project={project_id}
    and
    --region={region}
    (or
    --location
    for
    bq
    ) explicitly on each command instead of running
    gcloud config set
    , which persists beyond the task. Default to
    us-central1
    when the user has not specified a region (see BigQuery Locations).
  2. Enable Required APIs:
    • For SQL, JavaScript, and offline Python UDFs:
      bigquery.googleapis.com
    • Additionally for Python UDFs calling APIs (
      WITH CONNECTION
      ) and Remote Functions:
      bigqueryconnection.googleapis.com
      (and
      run.googleapis.com
      for Remote Functions)
    bash
    CLOUDSDK_METRICS_REQUEST_ATTRIBUTION="agent-skills/1.0 (skill:bigquery-udfs)" \
    gcloud services enable bigquery.googleapis.com \
      bigqueryconnection.googleapis.com \
      run.googleapis.com --quiet
  3. Verify Required IAM Roles:
    • All UDFs:
      roles/bigquery.dataEditor
      on the dataset and
      roles/bigquery.jobUser
      on the project.
    • When using
      WITH CONNECTION
      (API-calling Python UDFs & Remote Functions)
      :
      • UDF Creator:
        roles/bigquery.connectionAdmin
        on the project (plus
        resourcemanager.projects.setIamPolicy
        , e.g.,
        roles/resourcemanager.projectIamAdmin
        , when granting project-level IAM roles to the connection service account via
        GRANT ... ON PROJECT
        ).
      • UDF Caller:
        roles/bigquery.connectionUser
        on the connection.

确保 Google Cloud 项目已关联有效的结算账号(请参阅 BigQuery Pricing):
  1. 安装并认证 Google Cloud SDK:安装 Google Cloud SDK 并完成认证:
    bash
    gcloud auth login
    每条命令都显式传入
    --project={project_id}
    和
    --region={region}
    (对于
    bq
    使用
    --location
    ),不要运行
    gcloud config set
    ,因为该设置会持续到当前任务之外。如果用户未指定区域,默认使用
    us-central1
    (请参阅 BigQuery Locations)。
  2. 启用所需 API:
    • 对于 SQL、JavaScript 和 Offline Python UDF:
      bigquery.googleapis.com
    • 对于调用 API 的 Python UDF(
      WITH CONNECTION
      )和 Remote Function,还需启用
      bigqueryconnection.googleapis.com
      (Remote Function 还需启用
      run.googleapis.com
      )
    bash
    CLOUDSDK_METRICS_REQUEST_ATTRIBUTION="agent-skills/1.0 (skill:bigquery-udfs)" \
    gcloud services enable bigquery.googleapis.com \
      bigqueryconnection.googleapis.com \
      run.googleapis.com --quiet
  3. 验证所需 IAM 角色:
    • 所有 UDF:数据集上的
      roles/bigquery.dataEditor
      ,以及项目上的
      roles/bigquery.jobUser
      。
    • 使用
      WITH CONNECTION
      时(调用 API 的 Python UDF 与 Remote Function)
      :
      • UDF 创建者:项目上的
        roles/bigquery.connectionAdmin
        ;通过
        GRANT ... ON PROJECT
        向连接服务账号授予项目级 IAM 角色时,还需要
        resourcemanager.projects.setIamPolicy
        权限,例如
        roles/resourcemanager.projectIamAdmin
        。
      • UDF 调用者:连接上的
        roles/bigquery.connectionUser
        。

Core Implementation Patterns

核心实现模式

1. SQL UDFs (Scalar & Templated)

1. SQL UDF(标量函数与模板化函数)

Use
CREATE OR REPLACE FUNCTION
for persistent UDFs or
CREATE TEMP FUNCTION
for query-scoped functions. Use
ANY TYPE
for polymorphic parameters:
sql
CREATE OR REPLACE FUNCTION `{project_id}.{dataset_id}.normalize_phone`(
  raw_phone STRING,
  country_code ANY TYPE
)
RETURNS STRING
AS (
  CONCAT('+', CAST(country_code AS STRING), '-', REGEXP_REPLACE(raw_phone, r'[^0-9]', ''))
);
See SQL and JavaScript UDFs for aggregate UDFs (
CREATE AGGREGATE FUNCTION
) and JavaScript Cloud Storage library loading.
对于持久化 UDF,使用
CREATE OR REPLACE FUNCTION
;对于查询作用域函数,使用
CREATE TEMP FUNCTION
。多态参数使用
ANY TYPE
:
sql
CREATE OR REPLACE FUNCTION `{project_id}.{dataset_id}.normalize_phone`(
  raw_phone STRING,
  country_code ANY TYPE
)
RETURNS STRING
AS (
  CONCAT('+', CAST(country_code AS STRING), '-', REGEXP_REPLACE(raw_phone, r'[^0-9]', ''))
);
请参阅 SQL 和 JavaScript UDF,了解聚合 UDF(
CREATE AGGREGATE FUNCTION
)和 JavaScript Cloud Storage 库加载。

2. JavaScript UDFs

2. JavaScript UDF

Use raw triple-quoted strings (
r"""..."""
) to avoid escaping backslashes:
sql
CREATE OR REPLACE FUNCTION `{project_id}.{dataset_id}.extract_url_query_keys`(
  url_str STRING
)
RETURNS ARRAY<STRING>
DETERMINISTIC
LANGUAGE js
OPTIONS (
  library = ['gs://{bucket_name}/libs/uri-parser.js']
)
AS r"""
  if (!url_str) return [];
  try {
    return URIParser.getQueryKeys(url_str);
  } catch (err) {
    return [];
  }
""";
使用原始三引号字符串(
r"""..."""
)以避免转义反斜杠:
sql
CREATE OR REPLACE FUNCTION `{project_id}.{dataset_id}.extract_url_query_keys`(
  url_str STRING
)
RETURNS ARRAY<STRING>
DETERMINISTIC
LANGUAGE js
OPTIONS (
  library = ['gs://{bucket_name}/libs/uri-parser.js']
)
AS r"""
  if (!url_str) return [];
  try {
    return URIParser.getQueryKeys(url_str);
  } catch (err) {
    return [];
  }
""";

3. Managed Python UDFs (With and Without Connection)

3. 托管 Python UDF(使用和不使用 Connection)

Python UDFs must be persistent (do not use
TEMP
), specify
runtime_version = 'python-3.11'
, and define an
entry_point
.
numpy
,
pandas
, and
pyarrow
are pre-installed in the
python-3.11
base image.
BigQuery defaults to
container_memory = '512Mi'
,
container_cpu = 1.0
, and
container_request_concurrency = 80
. Omit these options when the defaults are sufficient, and configure them explicitly only when a workload requires custom container sizing or concurrency (see Python UDFs).
Top-level Python statements (
import
, helper functions, classes, and
def {entry_point}(...)
) inside
AS r'''...'''
must have zero leading indentation (flush to the left margin). Indenting top-level Python definitions to align with surrounding SQL causes an
IndentationError
when BigQuery loads the container module.
Python UDF 必须是持久化函数(不要使用
TEMP
),需要指定
runtime_version = 'python-3.11'
并定义
entry_point
。
numpy
、
pandas
和
pyarrow
已预装在
python-3.11
基础镜像中。
BigQuery 默认使用
container_memory = '512Mi'
、
container_cpu = 1.0
和
container_request_concurrency = 80
。如果默认值已足够,则省略这些选项;仅当工作负载需要自定义容器规格或并发度时才显式配置(请参阅 Python UDF)。
AS r'''...'''
内的顶层 Python 语句(
import
、辅助函数、类以及
def {entry_point}(...)
)必须完全没有前导缩进(与左边界齐平)。如果将顶层 Python 定义缩进以与周围 SQL 对齐,BigQuery 加载容器模块时会导致
IndentationError
。

A. Offline / Vectorized Python UDF (No Connection Needed)

A. Offline / 向量化 Python UDF(无需 Connection)

Omit
WITH CONNECTION
when the UDF only performs computation or uses PyPI packages (
packages=[...]
) / Cloud Storage libraries (
library=['gs://...']
). To vectorize execution over batches of rows, annotate the parameter with
pd.DataFrame
(or
pyarrow.RecordBatch
) and return a
pd.Series
:
[!WARNING] Vectorized operations must be row-independent: BigQuery calls vectorized UDFs on arbitrary row batches (up to
max_batching_rows
). Do NOT compute global column statistics (such as z-scores, dataset mean/std, or rank) across
df
, because each batch only sees an arbitrary slice of rows. Use SQL window functions (
(val - AVG(val) OVER()) / NULLIF(STDDEV(val) OVER(), 0)
) for dataset-wide statistics. Vectorized Python UDFs should perform row-independent calculations (e.g. geometric distances or multi-column math).
sql
CREATE OR REPLACE FUNCTION `{project_id}.{dataset_id}.vectorized_distance`(
  x1 FLOAT64, y1 FLOAT64, x2 FLOAT64, y2 FLOAT64
)
RETURNS FLOAT64
LANGUAGE python
OPTIONS (
  runtime_version = 'python-3.11',
  entry_point = 'compute_distance'
)
AS r'''
import numpy as np
import pandas as pd

def compute_distance(df: pd.DataFrame) -> pd.Series:
    return pd.Series(
        np.hypot(df['x2'] - df['x1'], df['y2'] - df['y1']),
        index=df.index,
    )
''';
当 UDF 仅执行计算或使用 PyPI 包(
packages=[...]
)/ Cloud Storage 库(
library=['gs://...']
)时,省略
WITH CONNECTION
。 若要按批次对执行进行向量化,请使用
pd.DataFrame
标注参数(或使用
pyarrow.RecordBatch
),并返回
pd.Series
:
[!WARNING] 向量化操作必须与行无关:BigQuery 会使用任意行批次(最多
max_batching_rows
)调用向量化 UDF。不要跨
df
计算全局列统计量(例如 z-score、数据集均值/标准差或排名),因为每个批次只能看到任意一部分行。对于数据集范围的统计量,请使用 SQL 窗口函数(
(val - AVG(val) OVER()) / NULLIF(STDDEV(val) OVER(), 0)
)。向量化 Python UDF 应执行与行无关的计算(例如几何距离或多列数学运算)。
sql
CREATE OR REPLACE FUNCTION `{project_id}.{dataset_id}.vectorized_distance`(
  x1 FLOAT64, y1 FLOAT64, x2 FLOAT64, y2 FLOAT64
)
RETURNS FLOAT64
LANGUAGE python
OPTIONS (
  runtime_version = 'python-3.11',
  entry_point = 'compute_distance'
)
AS r'''
import numpy as np
import pandas as pd

def compute_distance(df: pd.DataFrame) -> pd.Series:
    return pd.Series(
        np.hypot(df['x2'] - df['x1'], df['y2'] - df['y1']),
        index=df.index,
    )
''';

B. Online Python UDF Calling an External / Cloud API (
WITH CONNECTION
)

B. 调用外部或 Cloud API 的 Online Python UDF(
WITH CONNECTION
)

Include
WITH CONNECTION
only when the Python code makes outbound network or API calls at runtime.
Always configure explicit timeouts, logging, and prescriptive exception handling in the
try...except
block:
  • Transient errors only →
    NULL
    : Catch retryable exceptions (
    google.api_core.exceptions.TooManyRequests
    ,
    ServiceUnavailable
    ,
    DeadlineExceeded
    ,
    InternalServerError
    , and
    RetryError
    ), log them with
    logging.warning
    , and return
    None
    so a transient blip does not abort the query. Do not catch the base class
    GoogleAPICallError
    here: it also matches
    PermissionDenied
    ,
    Unauthenticated
    , and
    InvalidArgument
    .
  • Fatal errors → raise: Let auth, permission, and invalid-argument errors propagate (or log and re-raise as
    RuntimeError
    ) so they surface as a user error on the query instead of silently producing
    NULL
    s.
  • Never log row values: Anyone with Cloud Logging access can read UDF logs regardless of BigQuery table permissions. Log exception types and messages, not input or output data. Logs are only emitted when the session sets
    SET @@udf.properties = JSON '{"enableDebugOutput": true}';
    .
  • Set a per-request
    timeout
    :
    Retry(timeout=...)
    only caps the total retry duration; also pass
    timeout=
    on each client call.
  1. Create a Cloud Resource Connection and Retrieve its Service Account:
    bash
    bq mk --connection --connection_type=CLOUD_RESOURCE \
      --location={region} --project_id={project_id} {connection_id}
    
    bq show --connection {project_id}.{region}.{connection_id}
  2. Grant Permissions to the Connection Service Account: Grant
    roles/serviceusage.serviceUsageConsumer
    on
    {project_id}
    plus the required API role (e.g.,
    roles/cloudtranslate.user
    ) on the target project. Running
    GRANT ... ON PROJECT
    modifies the project's IAM policy and requires
    resourcemanager.projects.setIamPolicy
    (for example,
    roles/resourcemanager.projectIamAdmin
    ); confirm with the user before running project-level IAM grants. The DCL
    connection:
    grantee takes the connection path (
    [project_id.]location.connection_id
    ), not the service account email; BigQuery resolves the connection's service account automatically (use
    "serviceAccount:{connection_sa_email}"
    to grant by email instead):
    sql
    GRANT `roles/serviceusage.serviceUsageConsumer`
    ON PROJECT `{project_id}`
    TO "connection:{project_id}.{region}.{connection_id}";
    
    GRANT `roles/cloudtranslate.user`
    ON PROJECT `{project_id}`
    TO "connection:{project_id}.{region}.{connection_id}";
  3. Create the Python UDF with
    WITH CONNECTION
    (keep top-level Python statements flush-left at column 0):
sql
CREATE OR REPLACE FUNCTION `{project_id}.{dataset_id}.translate_to_es`(
  text STRING
)
RETURNS STRING
LANGUAGE python
WITH CONNECTION `{project_id}.{region}.{connection_id}`
OPTIONS (
  entry_point = 'do_translate',
  runtime_version = 'python-3.11',
  packages = ['google-cloud-translate>=3.11', 'google-api-core']
)
AS r'''
import logging
from google.api_core import exceptions
from google.api_core.retry import Retry
from google.cloud import translate

client = translate.TranslationServiceClient()

TRANSIENT_ERRORS = (
    exceptions.TooManyRequests,
    exceptions.ServiceUnavailable,
    exceptions.DeadlineExceeded,
    exceptions.InternalServerError,
    exceptions.RetryError,
)

def do_translate(text: str) -> str:
    if not text:
        return None
    try:
        # Note: Replace {project_id} with your Google Cloud Project ID
        response = client.translate_text(
            request={
                "parent": "projects/{project_id}/locations/us-central1",
                "contents": [text],
                "target_language_code": "es",
                "mime_type": "text/plain",
            },
            retry=Retry(timeout=30.0),  # Total retry budget.
            timeout=10.0,  # Per-attempt deadline.
        )
        return response.translations[0].translated_text
    except TRANSIENT_ERRORS as e:
        # Log the error type only; never log row values.
        logging.warning("Transient Translation API error: %s", type(e).__name__)
        return None
    except exceptions.GoogleAPICallError as e:
        # PermissionDenied, Unauthenticated, InvalidArgument, etc. are fatal.
        logging.error("Fatal Translation API error: %s: %s", type(e).__name__, e)
        raise RuntimeError(f"Translation failed: {type(e).__name__}") from e
''';
See Python UDFs for container sizing (
container_cpu
,
container_memory
,
container_request_concurrency
), Cloud Logging (
SET @@udf.properties = JSON '{"enableDebugOutput": true}';
), and checking container build status via
INFORMATION_SCHEMA.ROUTINES
.
仅当 Python 代码在运行时发起出站网络或 API 调用时,才包含
WITH CONNECTION
。
始终在
try...except
块中配置明确的超时、日志和可操作的异常处理:
  • 仅瞬时错误 →
    NULL
    :捕获可重试异常(
    google.api_core.exceptions.TooManyRequests
    、
    ServiceUnavailable
    、
    DeadlineExceeded
    、
    InternalServerError
    和
    RetryError
    ),使用
    logging.warning
    记录,并返回
    None
    ,这样瞬时故障不会中止查询。不要在此捕获基类
    GoogleAPICallError
    ,因为它还会匹配
    PermissionDenied
    、
    Unauthenticated
    和
    InvalidArgument
    。
  • 致命错误 → 抛出:让身份验证、权限和无效参数错误向上传播(或记录后重新抛出为
    RuntimeError
    ),从而在查询中显示为用户错误,而不是静默产生
    NULL
    。
  • 绝不记录行值:任何拥有 Cloud Logging 访问权限的人,无论其 BigQuery 表权限如何,都可以读取 UDF 日志。仅记录异常类型和消息,不记录输入或输出数据。仅当会话设置
    SET @@udf.properties = JSON '{"enableDebugOutput": true}';
    后才会输出日志。
  • 设置每次请求的
    timeout
    :
    Retry(timeout=...)
    只会限制总重试时长;还必须在每次客户端调用中传入
    timeout=
    。
  1. 创建 Cloud Resource Connection 并获取其服务账号:
    bash
    bq mk --connection --connection_type=CLOUD_RESOURCE \
      --location={region} --project_id={project_id} {connection_id}
    
    bq show --connection {project_id}.{region}.{connection_id}
  2. 向 Connection 服务账号授予权限:向
    {project_id}
    授予
    roles/serviceusage.serviceUsageConsumer
    ,并在目标项目上授予所需的 API 角色(例如
    roles/cloudtranslate.user
    )。运行
    GRANT ... ON PROJECT
    会修改项目的 IAM 策略,并要求具备
    resourcemanager.projects.setIamPolicy
    权限(例如
    roles/resourcemanager.projectIamAdmin
    );执行项目级 IAM 授权前,务必与用户确认。DCL
    connection:
    被授权方使用的是连接路径(
    [project_id.]location.connection_id
    ),而不是服务账号邮箱;BigQuery 会自动解析连接的服务账号(也可以改用
    "serviceAccount:{connection_sa_email}"
    按邮箱授权):
    sql
    GRANT `roles/serviceusage.serviceUsageConsumer`
    ON PROJECT `{project_id}`
    TO "connection:{project_id}.{region}.{connection_id}";
    
    GRANT `roles/cloudtranslate.user`
    ON PROJECT `{project_id}`
    TO "connection:{project_id}.{region}.{connection_id}";
  3. 使用
    WITH CONNECTION
    创建 Python UDF
    (Python 顶层语句保持第 0 列顶格):
sql
CREATE OR REPLACE FUNCTION `{project_id}.{dataset_id}.translate_to_es`(
  text STRING
)
RETURNS STRING
LANGUAGE python
WITH CONNECTION `{project_id}.{region}.{connection_id}`
OPTIONS (
  entry_point = 'do_translate',
  runtime_version = 'python-3.11',
  packages = ['google-cloud-translate>=3.11', 'google-api-core']
)
AS r'''
import logging
from google.api_core import exceptions
from google.api_core.retry import Retry
from google.cloud import translate

client = translate.TranslationServiceClient()

TRANSIENT_ERRORS = (
    exceptions.TooManyRequests,
    exceptions.ServiceUnavailable,
    exceptions.DeadlineExceeded,
    exceptions.InternalServerError,
    exceptions.RetryError,
)

def do_translate(text: str) -> str:
    if not text:
        return None
    try:
        # Note: Replace {project_id} with your Google Cloud Project ID
        response = client.translate_text(
            request={
                "parent": "projects/{project_id}/locations/us-central1",
                "contents": [text],
                "target_language_code": "es",
                "mime_type": "text/plain",
            },
            retry=Retry(timeout=30.0),  # Total retry budget.
            timeout=10.0,  # Per-attempt deadline.
        )
        return response.translations[0].translated_text
    except TRANSIENT_ERRORS as e:
        # Log the error type only; never log row values.
        logging.warning("Transient Translation API error: %s", type(e).__name__)
        return None
    except exceptions.GoogleAPICallError as e:
        # PermissionDenied, Unauthenticated, InvalidArgument, etc. are fatal.
        logging.error("Fatal Translation API error: %s: %s", type(e).__name__, e)
        raise RuntimeError(f"Translation failed: {type(e).__name__}") from e
''';
请参阅 Python UDF,了解容器规格配置(
container_cpu
、
container_memory
、
container_request_concurrency
)、Cloud Logging(
SET @@udf.properties = JSON '{"enableDebugOutput": true}';
),以及如何通过
INFORMATION_SCHEMA.ROUTINES
检查容器构建状态。

4. Remote Functions (Cloud Run Endpoints)

4. Remote Function(Cloud Run 端点)

Use Remote Functions when the endpoint is hosted on Cloud Run or Cloud Run functions (for non-Python languages, VPC networking, or custom hardware):
  1. Grant
    roles/run.invoker
    to the Connection Service Account
    (confirm with the user before modifying the Cloud Run service IAM policy):
    bash
    CLOUDSDK_METRICS_REQUEST_ATTRIBUTION="agent-skills/1.0 (skill:bigquery-udfs)" \
    gcloud run services add-iam-policy-binding {cloud_run_service} \
      --region={region} \
      --member="serviceAccount:{connection_sa_email}" \
      --role="roles/run.invoker"
  2. Register the Remote Function: The endpoint must accept
    {"calls": [[arg1, ...], ...]}
    and return
    {"replies": [res1, ...]}
    with matching element count:
    sql
    CREATE OR REPLACE FUNCTION `{project_id}.{dataset_id}.enrich_address`(
      street STRING, postal_code STRING
    )
    RETURNS JSON
    REMOTE WITH CONNECTION `{project_id}.{region}.{connection_id}`
    OPTIONS (
      endpoint = 'https://{cloud_run_service_url}',
      max_batching_rows = 1000
    );
See Remote Functions for Cloud Run handler templates and retry handling.

当端点托管于 Cloud Run 或 Cloud Run functions 上,或需要非 Python 语言、VPC 网络或自定义硬件时,使用 Remote Function:
  1. 向 Connection 服务账号授予
    roles/run.invoker
    (在修改 Cloud Run 服务的 IAM 策略前,先与用户确认):
    bash
    CLOUDSDK_METRICS_REQUEST_ATTRIBUTION="agent-skills/1.0 (skill:bigquery-udfs)" \
    gcloud run services add-iam-policy-binding {cloud_run_service} \
      --region={region} \
      --member="serviceAccount:{connection_sa_email}" \
      --role="roles/run.invoker"
  2. 注册 Remote Function:端点必须接受
    {"calls": [[arg1, ...], ...]}
    ,并返回
    {"replies": [res1, ...]}
    ,且两个数组的元素数量必须一致:
sql
CREATE OR REPLACE FUNCTION `{project_id}.{dataset_id}.enrich_address`(
  street STRING, postal_code STRING
)
RETURNS JSON
REMOTE WITH CONNECTION `{project_id}.{region}.{connection_id}`
OPTIONS (
  endpoint = 'https://{cloud_run_service_url}',
  max_batching_rows = 1000
);
请参阅 Remote Function,了解 Cloud Run handler 模板和重试处理。

Validation Checklist

验证清单

After generating or modifying a UDF, follow this validate→fix→repeat loop:
  • Step 1 — Validate Python code before BigQuery DDL: For Python UDFs, validate the Python function and
    packages
    dependencies before submitting the BigQuery DDL—either locally with
    python3
    test inputs (
    None
    , edge cases,
    pd.DataFrame
    batches) or in a containerized Cloud Run Job (
    gcloud run jobs deploy {job_name} --source . --region={region}
    and
    gcloud run jobs execute {job_name} --region={region} --wait
    ; see Python UDFs Validation).
  • Step 2 — Execute DDL and poll container build status: Run
    CREATE OR REPLACE FUNCTION
    . Because the DDL statement returns before the Python container image finishes building, poll
    INFORMATION_SCHEMA.ROUTINES
    until
    build_state
    transitions from
    IN_PROGRESS
    to
    SUCCEEDED
    (or fix and re-run if
    FAILED
    ):
    sql
    SELECT build_status.*
    FROM `{project_id}.{dataset_id}`.INFORMATION_SCHEMA.ROUTINES
    WHERE routine_name = '{udf_name}';
  • Step 3 — Test the UDF with SQL
    SELECT
    : Once
    build_state = 'SUCCEEDED'
    (or immediately after DDL for SQL/JS UDFs), run a test
    SELECT
    query covering
    NULL
    and valid inputs.
生成或修改 UDF 后,请遵循“验证 → 修复 → 重复”的循环:
  • 步骤 1 — 在 BigQuery DDL 之前验证 Python 代码:对于 Python UDF,在提交 BigQuery DDL 之前验证 Python 函数及
    packages
    依赖项——可以在本地使用
    python3
    配合测试输入(
    None
    、边界用例、
    pd.DataFrame
    批次)进行验证,也可以使用容器化的 Cloud Run Job(
    gcloud run jobs deploy {job_name} --source . --region={region}
    和
    gcloud run jobs execute {job_name} --region={region} --wait
    ;请参阅 Python UDF 验证)。
  • 步骤 2 — 执行 DDL 并轮询容器构建状态:运行
    CREATE OR REPLACE FUNCTION
    。由于 DDL 语句会在 Python 容器镜像构建完成之前返回,因此需轮询
    INFORMATION_SCHEMA.ROUTINES
    ,直至
    build_state
    从
    IN_PROGRESS
    转换为
    SUCCEEDED
    (如果为
    FAILED
    ,则修复后重新运行):
sql
SELECT build_status.*
FROM `{project_id}.{dataset_id}`.INFORMATION_SCHEMA.ROUTINES
WHERE routine_name = '{udf_name}';
  • 步骤 3 — 使用 SQL
    SELECT
    测试 UDF
    :当
    build_state = 'SUCCEEDED'
    时(SQL/JS UDF 则可在执行 DDL 后立即测试),运行覆盖
    NULL
    和有效输入的测试
    SELECT
    查询。

Cleanup & Teardown

清理与拆除

Delete unused routines, connections, Cloud Run services, and staged Cloud Storage artifacts (note that the size of all Python UDF containers per project and per region is restricted to a sum total of 10 GiB):
bash
bq query --use_legacy_sql=false "DROP FUNCTION IF EXISTS \`{project_id}.{dataset_id}.{udf_name}\`;"
bq rm --connection --location={region} {connection_id}
CLOUDSDK_METRICS_REQUEST_ATTRIBUTION="agent-skills/1.0 (skill:bigquery-udfs)" \
gcloud run services delete {cloud_run_service} --region={region} --project={project_id}
CLOUDSDK_METRICS_REQUEST_ATTRIBUTION="agent-skills/1.0 (skill:bigquery-udfs)" \
gcloud storage rm gs://{bucket_name}/udf_libs/bundle.js
删除未使用的例程、连接、Cloud Run 服务及已暂存的 Cloud Storage 构件(请注意,每个项目、每个区域的所有 Python UDF 容器总大小限制为 10 GiB):
bash
bq query --use_legacy_sql=false "DROP FUNCTION IF EXISTS \`{project_id}.{dataset_id}.{udf_name}\`;"
bq rm --connection --location={region} {connection_id}
CLOUDSDK_METRICS_REQUEST_ATTRIBUTION="agent-skills/1.0 (skill:bigquery-udfs)" \
gcloud run services delete {cloud_run_service} --region={region} --project={project_id}
CLOUDSDK_METRICS_REQUEST_ATTRIBUTION="agent-skills/1.0 (skill:bigquery-udfs)" \
gcloud storage rm gs://{bucket_name}/udf_libs/bundle.js

Reference Directory

参考目录

  • SQL and JavaScript UDFs: Templated SQL parameters (
    ANY TYPE
    ), aggregate UDFs, JavaScript type mappings, and Cloud Storage library loading (
    https://docs.cloud.google.com/bigquery/docs/user-defined-functions.md.txt
    ).
  • Python UDFs: Offline vs.
    WITH CONNECTION
    online service access, Pandas/PyArrow vectorization, container resource limits (
    container_cpu
    /
    container_memory
    ), and Cloud Logging debugging (
    https://docs.cloud.google.com/bigquery/docs/user-defined-functions-python.md.txt
    ).
  • Remote Functions: Cloud Run HTTP request and response JSON schema, batch sizing, retry semantics, and VPC egress (
    https://docs.cloud.google.com/bigquery/docs/remote-functions.md.txt
    ).
  • IAM, Authorized Routines, and Quotas: Sharing routines across datasets (
    Authorized Routines
    ), container quotas, and troubleshooting errors.
  • SQL 和 JavaScript UDF:模板化 SQL 参数(
    ANY TYPE
    )、聚合 UDF、JavaScript 类型映射和 Cloud Storage 库加载(
    https://docs.cloud.google.com/bigquery/docs/user-defined-functions.md.txt
    )。
  • Python UDF:Offline 与通过
    WITH CONNECTION
    进行的在线服务访问、Pandas/PyArrow 向量化、容器资源限制(
    container_cpu
    /
    container_memory
    )以及 Cloud Logging 调试(
    https://docs.cloud.google.com/bigquery/docs/user-defined-functions-python.md.txt
    )。
  • Remote Function:Cloud Run HTTP 请求和响应 JSON 模式、批处理大小、重试语义及 VPC 出口(
    https://docs.cloud.google.com/bigquery/docs/remote-functions.md.txt
    )。
  • IAM、Authorized Routines 与配额:跨数据集共享例程(Authorized Routines)、容器配额和错误排查。

Related Skills

相关 Skill

  • BigQuery Basics (
    bigquery-basics
    ): Dataset, table, and job management.
  • BigQuery DataFrames: Creating Python UDFs from Python via
    @bpd.udf
    .
  • BigQuery AI & ML: Built-in
    ML.GENERATE_TEXT
    and
    AI.GENERATE
    functions.
  • BigQuery Basics(
    bigquery-basics
    ):数据集、表和作业管理。
  • BigQuery DataFrames:通过
    @bpd.udf
    从 Python 创建 Python UDF。
  • BigQuery AI & ML:内置
    ML.GENERATE_TEXT
    和
    AI.GENERATE
    函数。