Utilizza le funzioni definite dall'utente in Python

Una funzione definita dall'utente (UDF) Python consente di implementare una funzione scalare in Python e utilizzarla in una query SQL. Le funzioni definite dall'utente in Python sono simili alle funzioni definite dall'utente in SQL e JavaScript, ma con funzionalità aggiuntive. Le UDF Python ti consentono di installare librerie di terze parti dal Python Package Index (PyPI) e di accedere ai servizi esterni utilizzando una connessione alle risorse Cloud.

Le funzioni definite dall'utente Python vengono create ed eseguite su risorse gestite di BigQuery.

Limitazioni

  • python-3.11 è l'unico runtime supportato.
  • Non puoi creare una funzione definita dall'utente Python temporanea.
  • Non puoi utilizzare una funzione definita dall'utente Python con una vista materializzata.
  • I risultati di una query che chiama una funzione definita dall'utente Python non vengono memorizzati nella cache perché il valore restituito di una funzione definita dall'utente Python viene sempre considerato non deterministico.
  • Assured Workloads non è supportato.
  • Questi tipi di dati non sono supportati: JSON, RANGE, INTERVAL e GEOGRAPHY.
  • I container che eseguono funzioni definite dall'utente Python possono essere configurati solo fino a 4 vCPU e 16 GiB.
  • La crittografia del codice UDF Python con chiavi di crittografia gestite dal cliente (CMEK) non è supportata.
  • Le funzioni definite dall'utente Python supportano i Controlli di servizio VPC, ma le reti VPC non sono supportate.

Ruoli obbligatori

I ruoli IAM richiesti dipendono dal fatto che tu sia proprietario o utente di una funzione definita dall'utente Python.

Proprietari di UDF

In genere, un proprietario di una funzione definita dall'utente Python crea o aggiorna una funzione definita dall'utente. Se crei una funzione definita dall'utente Python che fa riferimento a una connessione alle risorse Cloud, sono necessari anche ruoli aggiuntivi. Questa connessione è obbligatoria solo se la funzione definita dall'utente utilizza la clausola WITH CONNECTION per accedere a un servizio esterno.

Per ottenere le autorizzazioni necessarie per creare o aggiornare una funzione definita dall'utente Python, chiedi all'amministratore di concederti i seguenti ruoli IAM:

Per saperne di più sulla concessione dei ruoli, consulta Gestisci l'accesso a progetti, cartelle e organizzazioni.

Questi ruoli predefiniti contengono le autorizzazioni necessarie per creare o aggiornare una funzione definita dall'utente Python. Per vedere quali sono esattamente le autorizzazioni richieste, espandi la sezione Autorizzazioni obbligatorie:

Autorizzazioni obbligatorie

Per creare o aggiornare una funzione definita dall'utente Python sono necessarie le seguenti autorizzazioni:

  • Crea una funzione definita dall'utente Python utilizzando l'istruzione CREATE FUNCTION: bigquery.routines.create sul set di dati
  • Aggiorna una funzione definita dall'utente Python utilizzando l'istruzione CREATE FUNCTION: bigquery.routines.update sul set di dati
  • Esegui un job di query con istruzione CREATE FUNCTION: bigquery.jobs.create sul progetto
  • Crea una nuova connessione alle risorse Cloud: bigquery.connections.create sul progetto
  • Utilizza una connessione nell'istruzione CREATE FUNCTION: bigquery.connections.delegate sulla connessione

Potresti anche ottenere queste autorizzazioni con ruoli personalizzati o altri ruoli predefiniti.

Per saperne di più sui ruoli in BigQuery, consulta Ruoli IAM predefiniti.

Utenti UDF

Un utente di una funzione definita dall'utente Python richiama una funzione definita dall'utente creata da un altro utente. Sono richiesti ruoli aggiuntivi anche se richiami una funzione definita dall'utente Python che fa riferimento a una connessione alle risorse Cloud.

Per ottenere le autorizzazioni necessarie per richiamare una funzione definita dall'utente Python creata da un altro utente, chiedi all'amministratore di concederti i seguenti ruoli IAM:

Per saperne di più sulla concessione dei ruoli, consulta Gestisci l'accesso a progetti, cartelle e organizzazioni.

Questi ruoli predefiniti contengono le autorizzazioni necessarie per richiamare una funzione definita dall'utente Python creata da un altro utente. Per vedere quali sono esattamente le autorizzazioni richieste, espandi la sezione Autorizzazioni obbligatorie:

Autorizzazioni obbligatorie

Per richiamare una funzione definita dall'utente Python creata da un altro utente, sono necessarie le seguenti autorizzazioni:

  • Per eseguire un job di query che fa riferimento a una funzione definita dall'utente Python: bigquery.jobs.create sul progetto
  • Per richiamare una funzione definita dall'utente Python creata da un altro utente: bigquery.routines.get sul set di dati
  • Per eseguire una funzione definita dall'utente Python che fa riferimento a una connessione alle risorse Cloud: bigquery.connections.use sulla connessione

Potresti anche ottenere queste autorizzazioni con ruoli personalizzati o altri ruoli predefiniti.

Per saperne di più sui ruoli in BigQuery, consulta Ruoli IAM predefiniti.

Crea una funzione definita dall'utente Python permanente

Segui queste regole quando crei una funzione definita dall'utente Python:

  • Il corpo della funzione definita dall'utente Python deve essere un valore letterale stringa tra virgolette che rappresenta il codice Python. Per scoprire di più sui valori letterali stringa tra virgolette, consulta Formati per i valori letterali tra virgolette.

  • Il corpo della funzione definita dall'utente Python deve includere una funzione Python utilizzata nell'argomento entry_point nell'elenco di opzioni della funzione definita dall'utente Python.

  • È necessario specificare una versione del runtime Python nell'opzione runtime_version. L'unica versione del runtime Python supportata è python-3.11. Per un elenco completo delle opzioni disponibili, consulta l'elenco delle opzioni delle funzioni per l'istruzione CREATE FUNCTION.

Per creare una funzione definita dall'utente Python permanente, utilizza l'istruzione CREATE FUNCTION senza la parola chiave TEMP o TEMPORARY. Per eliminare una funzione definita dall'utente Python permanente, utilizza l'istruzione DROP FUNCTION.

Esempio

Per visualizzare un esempio di creazione di una funzione definita dall'utente Python permanente, scegli una delle seguenti opzioni:

Console

L'esempio seguente crea una funzione definita dall'utente Python permanente denominata multiplyInputs e la chiama dall'interno di un'istruzione SELECT:

  1. Vai alla pagina BigQuery.

    Vai a BigQuery

  2. Nell'editor di query, inserisci la seguente istruzione CREATE FUNCTION:

    CREATE FUNCTION `PROJECT_ID.DATASET_ID`.multiplyInputs(x FLOAT64, y FLOAT64)
    RETURNS FLOAT64
    LANGUAGE python
    OPTIONS(runtime_version="python-3.11", entry_point="multiply")
    AS r'''
    
    def multiply(x, y):
        return x * y
    
    ''';
    
    -- Call the Python UDF.
    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,
    `PROJECT_ID.DATASET_ID`.multiplyInputs(x, y) AS product
    FROM numbers;

    Sostituisci PROJECT_ID.DATASET_ID con l'ID progetto e l'ID set di dati.

  3. Fai clic su  Esegui.

    Questo esempio produce il seguente output:

    +-----+-----+--------------+
    | x   | y   | product      |
    +-----+-----+--------------+
    | 1   | 5   |  5.0         |
    | 2   | 10  | 20.0         |
    | 3   | 15  | 45.0         |
    +-----+-----+--------------+
    

BigQuery DataFrames

L'esempio seguente utilizza BigQuery DataFrames per trasformare una funzione personalizzata in una funzione definita dall'utente Python:

import bigframes.pandas as bpd

# Set BigQuery DataFrames options
bpd.options.bigquery.project = your_gcp_project_id
bpd.options.bigquery.location = "US"

# BigQuery DataFrames gives you the ability to turn your custom functions
# into a BigQuery Python UDF. One can find more details about the usage and
# the requirements via `help` command.
help(bpd.udf)

# Read a table and inspect the column of interest.
df = bpd.read_gbq("bigquery-public-data.ml_datasets.penguins")
df["body_mass_g"].peek(10)

# Define a custom function, and specify the intent to turn it into a
# BigQuery Python UDF. Let's try a `pandas`-like use case in which we want
# to apply a user defined function to every value in a `Series`, more
# specifically bucketize the `body_mass_g` value of the penguins, which is a
# real number, into a category, which is a string.
@bpd.udf(
    dataset=your_bq_dataset_id,
    name=your_bq_routine_id,
)
def get_bucket(num: float) -> str:
    if not num:
        return "NA"
    boundary = 4000
    return "at_or_above_4000" if num >= boundary else "below_4000"

# Then we can apply the udf on the `Series` of interest via
# `apply` API and store the result in a new column in the DataFrame.
df = df.assign(body_mass_bucket=df["body_mass_g"].apply(get_bucket))

# This will add a new column `body_mass_bucket` in the DataFrame. You can
# preview the original value and the bucketized value side by side.
df[["body_mass_g", "body_mass_bucket"]].peek(10)

# The above operation was possible by doing all the computation on the
# cloud through an underlying BigQuery Python UDF that was created to
# support the user's operations in the Python code.

# The BigQuery Python UDF created to support the BigQuery DataFrames
# udf can be located via a property `bigframes_bigquery_function`
# set in the udf object.
print(f"Created BQ Python UDF: {get_bucket.bigframes_bigquery_function}")

# If you have already defined a custom function in BigQuery, either via the
# BigQuery Google Cloud Console or with the `udf` decorator,
# or otherwise, you may use it with BigQuery DataFrames with the
# `read_gbq_function` method. More details are available via the `help`
# command.
help(bpd.read_gbq_function)

existing_get_bucket_bq_udf = get_bucket.bigframes_bigquery_function

# Here is an example of using `read_gbq_function` to load an existing
# BigQuery Python UDF.
df = bpd.read_gbq("bigquery-public-data.ml_datasets.penguins")
get_bucket_function = bpd.read_gbq_function(existing_get_bucket_bq_udf)

df = df.assign(body_mass_bucket=df["body_mass_g"].apply(get_bucket_function))
df.peek(10)

# Let's continue trying other potential use cases of udf. Let's say we
# consider the `species`, `island` and `sex` of the penguins sensitive
# information and want to redact that by replacing with their hash code
# instead. Let's define another scalar custom function and decorate it
# as a udf. The custom function in this example has external package
# dependency, which can be specified via `packages` parameter.
@bpd.udf(
    dataset=your_bq_dataset_id,
    name=your_bq_routine_id,
    packages=["cryptography"],
)
def get_hash(input: str) -> str:
    from cryptography.fernet import Fernet

    # handle missing value
    if input is None:
        input = ""

    key = Fernet.generate_key()
    f = Fernet(key)
    return f.encrypt(input.encode()).decode()

# We can use this udf in another `pandas`-like API `map` that
# can be applied on a DataFrame
df_redacted = df[["species", "island", "sex"]].map(get_hash)
df_redacted.peek(10)

# If the BigQuery routine is no longer needed, we can clean it up
# to free up any cloud quota
session = bpd.get_global_session()
session.bqclient.delete_routine(f"{your_bq_dataset_id}.{your_bq_routine_id}")

Stato della build del container

Quando crei una funzione definita dall'utente Python utilizzando l'istruzione CREATE FUNCTION, BigQuery crea o aggiorna un'immagine container basata su un'immagine di base. Il container viene creato sull'immagine di base utilizzando il tuo codice e le eventuali dipendenze dei pacchetti specificate.

La creazione del container è un processo a lunga esecuzione. La prima query dopo l'esecuzione dell'istruzione CREATE FUNCTION attende il completamento della creazione dell'immagine. Se non sono presenti dipendenze esterne, l'immagine container viene in genere creata in meno di un minuto.

La dimensione di tutti i container di funzioni definite dall'utente Python per progetto e per regione è limitata a un totale di 10 GiB. Per saperne di più, consulta Limiti delle funzioni definite dall'utente permanenti. La build del container non va a buon fine se il progetto ha raggiunto la quota.

Per visualizzare lo stato della build del container, scegli una delle seguenti opzioni:

Console

  1. Vai alla pagina Studio di BigQuery.

    Vai a Studio

  2. Nel riquadro a sinistra, espandi il progetto e fai clic su Set di dati.

  3. Fai clic sul link per aprire il set di dati che contiene la tua funzione definita dall'utente Python.

  4. Nella pagina del set di dati, fai clic sulla scheda Routine.

  5. Nella colonna ID routine, fai clic sulla funzione definita dall'utente Python.

  6. Nella pagina Informazioni funzione permanente puoi visualizzare lo stato della build, la durata della build e le dimensioni dell'immagine. Lo stato della build è uno dei seguenti:

    • In corso
    • Riuscito
    • Non riuscito

    Se una build non va a buon fine, la pagina delle informazioni sulla funzione fornisce messaggi di errore dettagliati per consentirti di risolvere i problemi come errori di sintassi o problemi di installazione di pacchetti esterni.

    La pagina Informazioni funzione permanente nella console.

SQL

Per eseguire query sui campi dello stato della build nella visualizzazione INFORMATION_SCHEMA.ROUTINES, segui questi passaggi:

  1. Vai alla pagina Studio di BigQuery.

    Vai a Studio

  2. Passa all'editor di query o fai clic su Query SQL.

  3. Inserisci la seguente query per recuperare i campi BUILD_STATUS dalla vista INFORMATION_SCHEMA.ROUTINES. La colonna BUILD_STATUS è di tipo STRUCT in GoogleSQL:

    SELECT
      build_status.*
    FROM
      `PROJECT_ID.DATASET_ID`.INFORMATION_SCHEMA.ROUTINES;
    

    Sostituisci PROJECT_ID.DATASET_ID con l'ID progetto e l'ID set di dati.

    L'output dovrebbe essere simile al seguente. I campi di errore vengono omessi:

    +---------------+--------------------------------+------------------------+------------------+
    | build_state   | build_state_update_time        | build_duration_seconds | image_size_bytes |
    +---------------+--------------------------------+------------------------+------------------+
    | SUCCEEDED     | 2026-05-14 17:21:49.736000 UTC |                     11 |             3167 |
    +---------------+--------------------------------+------------------------+------------------+
    

API

Visualizza lo stato della build del container utilizzando RoutineBuildStatus nell'API.

Crea una funzione definita dall'utente Python vettorializzata

Puoi implementare la funzione definita dall'utente Python per elaborare un batch di righe anziché una singola riga utilizzando la vettorizzazione. La vettorizzazione può migliorare le prestazioni delle query. Puoi creare una funzione definita dall'utente vettorizzata utilizzando Pandas o Apache Arrow.

Per controllare il comportamento di raggruppamento, specifica il numero massimo di righe in ogni gruppo utilizzando l'opzione max_batching_rows nell'elenco di opzioni CREATE OR REPLACE FUNCTION. Se specifichi max_batching_rows, BigQuery determina il numero di righe in un batch, fino al limite max_batching_rows. Se max_batching_rows non è specificato, il numero di righe da raggruppare in batch viene determinato automaticamente.

Utilizza Pandas

Una funzione definita dall'utente Python vettorizzata ha un singolo argomento pandas.DataFrame che deve essere annotato. L'argomento pandas.DataFrame ha lo stesso numero di colonne dei parametri della funzione definita dall'utente Python definiti nell'istruzione CREATE FUNCTION. I nomi delle colonne nell'argomento pandas.DataFrame hanno gli stessi nomi dei parametri della funzione definita dall'utente.

La funzione deve restituire un pandas.Series o un pandas.DataFrame a colonna singola con lo stesso numero di righe dell'input.

L'esempio seguente crea una funzione definita dall'utente Python vettorizzata denominata multiplyInputs con due parametri: x e y:

  1. Vai alla pagina BigQuery.

    Vai a BigQuery

  2. Nell'editor di query, inserisci la seguente istruzione CREATE FUNCTION:

    CREATE FUNCTION `PROJECT_ID.DATASET_ID`.multiplyVectorized(x FLOAT64, y FLOAT64)
    RETURNS FLOAT64
    LANGUAGE python
    OPTIONS(runtime_version="python-3.11", entry_point="vectorized_multiply")
    AS r'''
    import pandas as pd
    
    def vectorized_multiply(df: pd.DataFrame):
      return df['x'] * df['y']
    
    ''';

    Sostituisci PROJECT_ID.DATASET_ID con l'ID progetto e l'ID set di dati.

    La chiamata della funzione definita dall'utente è la stessa dell'esempio precedente.

  3. Fai clic su  Esegui.

Usa Apache Arrow

L'esempio seguente utilizza l'interfaccia RecordBatch di Apache Arrow. Quando utilizzi l'interfaccia RecordBatch, la funzione passa un batch di righe di colonne di lunghezza uguale all'entry point. L'esempio seguente utilizza Apache Arrow per creare una funzione definita dall'utente Python vettorizzata denominata multiplyVectorizedArrow.

  1. Vai alla pagina BigQuery.

    Vai a BigQuery

  2. Nell'editor di query, inserisci la seguente istruzione CREATE FUNCTION:

    CREATE FUNCTION `PROJECT_ID.DATASET_ID`.multiplyVectorizedArrow(x FLOAT64, y FLOAT64)
    RETURNS FLOAT64
    LANGUAGE python
    OPTIONS(
      runtime_version="python-3.11",
      entry_point="vectorized_multiply_arrow"
    )
    AS r'''
    import pyarrow as pa
    import pyarrow.compute as pc
    
    def vectorized_multiply_arrow(batch: pa.RecordBatch):
        # Access columns directly from the Arrow RecordBatch
        x = batch.column('x')
        y = batch.column('y')
    
        # Use pyarrow.compute for vectorized operations
        return pc.multiply(x, y)
    ''';

    Sostituisci PROJECT_ID.DATASET_ID con l'ID progetto e l'ID set di dati.

    La chiamata della funzione definita dall'utente è la stessa degli esempi precedenti.

  3. Fai clic su  Esegui.

Chiama una funzione definita dall'utente Python

Se disponi dell'autorizzazione per richiamare una funzione definita dall'utente Python, puoi chiamarla come qualsiasi altra funzione. Per utilizzare una funzione definita in un progetto diverso, utilizza il nome completo della funzione. Ad esempio, per chiamare una funzione di estrazione XML denominata cw_xml_extract in un altro progetto, completa i seguenti passaggi.

Console

  1. Vai alla pagina BigQuery.

    Vai a BigQuery

  2. Nell'editor di query, inserisci il seguente esempio:

    SELECT
      `PROJECT_ID.DATASET_ID`.`cw_xml_extract`(xml, '//title/text()') AS `title`
    FROM UNNEST([
      STRUCT('''<book id="1">
        <title>The Great Gatsby</title>
        <author>F. Scott Fitzgerald</author>
      </book>''' AS xml),
      STRUCT('''<book id="2">
        <title>1984</title>
        <author>George Orwell</author>
      </book>''' AS xml),
      STRUCT('''<book id="3">
        <title>Brave New World</title>
        <author>Aldous Huxley</author>
      </book>''' AS xml)
    ])
    
  3. Fai clic su  Esegui.

    Questo esempio produce il seguente output:

    +--------------------------+
    | title                    |
    +--------------------------+
    | The Great Gatsby         |
    | 1984                     |
    | Brave New World          |
    +--------------------------+
    

BigQuery DataFrames

L'esempio seguente utilizza i metodi BigQuery DataFrames sql_scalar, read_gbq_function e apply per chiamare una funzione definita dall'utente Python:

import textwrap
from typing import Tuple

import bigframes.pandas as bpd
import pandas as pd
import pyarrow as pa

# Set partial ordering mode for BigQuery DataFrames.
bpd.options.bigquery.ordering_mode = "partial"


def call_python_udf(
    project_id: str = "your-project-id",
    location: str = "US",
) -> Tuple[pd.Series, bpd.Series]:
    """Demonstrates calling a Python UDF using pandas and BigQuery DataFrames."""
    # Set the billing project to use for queries. This step is optional, as the
    # project can be inferred from your environment in many cases.
    bpd.options.bigquery.project = project_id

    # Since this example works with local data, set a processing location.
    bpd.options.bigquery.location = location

    # Create a sample series.
    xml_series = pd.Series(
        [
            textwrap.dedent(
                """
                <book id="1">
                    <title>The Great Gatsby</title>
                    <author>F. Scott Fitzgerald</author>
                </book>
                """
            ),
            textwrap.dedent(
                """
                <book id="2">
                    <title>1984</title>
                    <author>George Orwell</author>
                </book>
                """
            ),
            textwrap.dedent(
                """
                <book id="3">
                    <title>Brave New World</title>
                    <author>Aldous Huxley</author>
                </book>
                """
            ),
        ],
        dtype=pd.ArrowDtype(pa.string()),
    )
    df = pd.DataFrame({"xml": xml_series})

    # Use the BigQuery Accessor, which is automatically registered on pandas
    # DataFrames when you import bigframes. This example uses a function that
    # has been deployed to bigquery-utils for demonstration purposes. To use in
    # production, deploy the function at
    # https://github.com/GoogleCloudPlatform/bigquery-utils/blob/master/udfs/community/cw_xml_extract.sqlx
    # to your own project.
    titles_pandas = df.bigquery.sql_scalar(
        "`bqutil`.`fn`.cw_xml_extract({xml}, '//title/text()')",
    )

    # Alternatively, call read_gbq_function to get a pointer to the function
    # that can be applied on BigQuery DataFrames objects.
    cw_xml_extract = bpd.read_gbq_function("bqutil.fn.cw_xml_extract")
    xml_bigframes = bpd.read_pandas(xml_series)

    xpath_query = "//title/text()"
    titles_bigframes = xml_bigframes.apply(cw_xml_extract, args=(xpath_query,))
    return titles_pandas, titles_bigframes


# Run the sample:
# titles_pandas, titles_bigframes = call_python_udf("your-project-id", "US")

Tipi di dati delle funzioni definite dall'utente Python supportati

La tabella seguente definisce la mappatura tra i tipi di dati BigQuery, i tipi di dati Python e i tipi di dati Pandas:

Tipo di dati BigQuery Tipo di dati integrato di Python utilizzato dalla funzione definita dall'utente standard Tipo di dati Pandas utilizzato dalla funzione definita dall'utente vettorizzata Tipo di dati PyArrow utilizzato per ARRAY e STRUCT nella funzione definita dall'utente vettorizzata
BOOL bool BooleanDtype DataType(bool)
INT64 int Int64Dtype DataType(int64)
FLOAT64 float FloatDtype DataType(double)
STRING str StringDtype DataType(string)
BYTES bytes binary[pyarrow] DataType(binary)
TIMESTAMP

Parametro della funzione: datetime.datetime (con fuso orario UTC impostato)

Valore restituito dalla funzione: datetime.datetime (con qualsiasi fuso orario impostato)

Parametro della funzione: timestamp[us, tz=UTC][pyarrow]

Valore restituito dalla funzione: timestamp[us, tz=*][pyarrow]\(any timezone\)

TimestampType(timestamp[us]), con fuso orario
DATE datetime.date date32[pyarrow] DataType(date32[day])
TIME datetime.time time64[pyarrow] Time64Type(time64[us])
DATETIME datetime.datetime (senza fuso orario) timestamp[us][pyarrow] TimestampType(timestamp[us]), senza fuso orario
ARRAY list list<...>[pyarrow], dove il tipo di dati dell'elemento è un pandas.ArrowDtype ListType
STRUCT dict struct<...>[pyarrow], dove il tipo di dati del campo è unpandas.ArrowDtype StructType

Versioni di runtime supportate

Le funzioni definite dall'utente (UDF) Python di BigQuery supportano il runtime python-3.11. Questa versione di Python include alcuni pacchetti preinstallati aggiuntivi. Per le librerie di sistema, controlla l'immagine di base del runtime.

Versione runtime Versione Python Include
python-3.11 Python 3.11 numpy 1.26.3
pyarrow 14.0.2
pandas 2.1.4
python-dateutil 2.8.2
absl-py 2.0.0
pytz 2023.3.post1
tzdata 2023.4
six 1.16.0

Utilizza pacchetti di terze parti

Puoi utilizzare l'elenco di opzioni CREATE FUNCTION per utilizzare moduli diversi da quelli forniti dalla libreria standard Python e dai pacchetti preinstallati. Puoi installare i pacchetti dal Python Package Index (PyPI) o importare i file Python da Cloud Storage.

Installa un pacchetto dal Python Package Index

Quando installi un pacchetto, devi fornire il nome del pacchetto e, facoltativamente, puoi fornire la versione del pacchetto utilizzando gli identificatori della versione del pacchetto Python.

Se il pacchetto è nel runtime, viene utilizzato a meno che non venga specificata una versione particolare nell'elenco di opzioni CREATE FUNCTION. Se non viene specificata una versione del pacchetto e il pacchetto non è presente nel runtime, viene utilizzata l'ultima versione disponibile. Sono supportati solo i pacchetti con formato binario wheel.

L'esempio seguente mostra come creare una funzione definita dall'utente Python che installa il pacchetto scipy utilizzando l'elenco di opzioni CREATE OR REPLACE FUNCTION:

  1. Vai alla pagina BigQuery.

    Vai a BigQuery

  2. Nell'editor di query, inserisci la seguente istruzione CREATE FUNCTION:

    CREATE FUNCTION `PROJECT_ID.DATASET_ID`.area(radius FLOAT64)
    RETURNS FLOAT64 LANGUAGE python
    OPTIONS (entry_point='area_handler', runtime_version='python-3.11', packages=['scipy==1.15.3'])
    AS r"""
    import scipy
    
    def area_handler(radius):
      return scipy.constants.pi*radius*radius
    """;
    
    SELECT `PROJECT_ID.DATASET_ID`.area(4.5);

    Sostituisci PROJECT_ID.DATASET_ID con l'ID progetto e l'ID set di dati.

  3. Fai clic su  Esegui.

Importa file Python aggiuntivi come librerie

Puoi estendere le tue funzioni definite dall'utente Python utilizzando l'elenco di opzioni della funzione importando i file Python da Cloud Storage.

Nel codice Python della funzione definita dall'utente, puoi importare i file Python da Cloud Storage come moduli utilizzando l'istruzione import seguita dal percorso dell'oggetto Cloud Storage. Ad esempio, se importi gs://BUCKET_NAME/path/to/lib1.py, l'istruzione di importazione sarà import path.to.lib1.

Il nome file Python deve essere un identificatore Python. Ogni nome folder nel nome dell'oggetto (dopo /) deve essere un identificatore Python valido. All'interno dell'intervallo ASCII (U+0001..U+007F), negli identificatori possono essere utilizzati i seguenti caratteri:

  • Lettere maiuscole e minuscole dalla A alla Z.
  • Trattini bassi.
  • Le cifre da zero a nove, ma un numero non può apparire come primo carattere nell'identificatore.

L'esempio seguente mostra come creare una funzione definita dall'utente Python che importa il pacchetto della libreria client lib1.py da un bucket Cloud Storage denominato my_bucket:

  1. Vai alla pagina BigQuery.

    Vai a BigQuery

  2. Nell'editor di query, inserisci la seguente istruzione CREATE FUNCTION:

    CREATE FUNCTION `PROJECT_ID.DATASET_ID`.myFunc(a FLOAT64, b STRING)
    RETURNS STRING LANGUAGE python
    OPTIONS (
    entry_point='compute', runtime_version='python-3.11',
    library=['gs://BUCKET_NAME/PATH/lib1.py'])
    AS r"""
    import path.to.lib1 as lib1
    
    def compute(a, b):
      # doInterestingStuff is a function defined in
      # gs://BUCKET_NAME/PATH/lib1.py
      return lib1.doInterestingStuff(a, b);
    
    """;

    Sostituisci quanto segue:

    • PROJECT_ID: il tuo ID progetto.
    • DATASET_ID: l'ID del set di dati.
    • BUCKET_NAME: il nome del bucket Cloud Storage che contiene lib1.py.
    • PATH: il percorso del bucket Cloud Storage.
  3. Fai clic su  Esegui.

Configura i limiti dei container per le funzioni definite dall'utente Python

Puoi utilizzare l'elenco di opzioni CREATE FUNCTION per specificare i limiti di CPU, memoria e contemporaneità delle richieste dei container per i container che eseguono funzioni definite dall'utente Python.

Per impostazione predefinita, ai container vengono allocate le seguenti risorse:

  • La memoria allocata è 512Mi.
  • La CPU allocata è 1.0 vCPU.
  • Il limite di richieste in contemporanea del container è 80.

L'esempio seguente crea una funzione definita dall'utente Python utilizzando l'elenco di opzioni CREATE FUNCTION per specificare i limiti del container:

  1. Vai alla pagina BigQuery.

    Vai a BigQuery

  2. Nell'editor di query, inserisci la seguente istruzione CREATE FUNCTION:

    CREATE FUNCTION `PROJECT_ID.DATASET_ID`.square_area(length FLOAT64)
    RETURNS FLOAT64 LANGUAGE python
    OPTIONS (entry_point='square_area', runtime_version='python-3.11',
    container_memory='CONTAINER_MEMORY', container_cpu=CONTAINER_CPU, container_request_concurrency=CONTAINER_REQUEST_CONCURRENCY)
    AS r"""
    def square_area(length):
      return length*length
    """;
    
    SELECT `PROJECT_ID.DATASET_ID`.square_area(4.5);

    Sostituisci quanto segue:

    • PROJECT_ID.DATASET_ID: l'ID progetto e l'ID set di dati.
    • CONTAINER_MEMORY: il valore della memoria nel seguente formato: <integer_number><unit>. L'unità deve essere uno di questi valori: Mi (MiB), M (MB), Gi (GiB) o G (GB). Ad esempio, 2Gi.
    • CONTAINER_CPU: il valore della CPU. Le UDF Python supportano valori di CPU frazionari compresi tra 0.33 e 1.0 e valori di CPU non frazionari di 1, 2 e 4.
    • CONTAINER_REQUEST_CONCURRENCY: il numero massimo di richieste in parallelo per istanza di container della funzione definita dall'utente Python. Il valore deve essere un numero intero compreso tra 1 e 1000.
  3. Fai clic su  Esegui.

Valori della CPU supportati

Le UDF Python supportano valori di CPU frazionari compresi tra 0.33 e 1.0 e valori di CPU non frazionari di 1, 2 e 4. I container che eseguono UDF Python possono essere configurati fino a 4 vCPU. Il valore predefinito è 1.0. I valori di input frazionari vengono arrotondati a due cifre decimali prima di essere applicati al container.

Valori di memoria supportati

I container delle funzioni definite dall'utente Python supportano i valori di memoria nel seguente formato: <integer_number><unit>. L'unità deve essere uno di questi valori: Mi, M, Gi, G. La quantità minima di memoria che puoi configurare è 256Mi. La quantità massima di memoria che puoi configurare è 16Gi.

In base al valore di memoria scelto, devi anche specificare una quantità appropriata di CPU. La tabella seguente mostra i valori minimi e massimi della CPU per ogni valore di memoria:

Memoria CPU minima CPU massima
Da 256Mi a 512Mi 0.33 2
Maggiore di 512Mi e minore o uguale a 1Gi 0.5 2
Maggiore di 1Gi e inferiore a 2Gi 1 2
Da 2Gi a 4Gi 1 4
Superiore a 4Gi e fino a 8Gi 2 4
Superiore a 8Gi e fino a 16Gi 4 4

In alternativa, se hai determinato la quantità di CPU che stai allocando, puoi utilizzare la tabella seguente per determinare l'intervallo di memoria appropriato:

CPU Memoria minima Memoria massima
Meno di 0.5 256Mi 512Mi
Da 0.5 a meno di 1 256Mi 1Gi
1 256Mi 4Gi
2 256Mi 8Gi
4 2Gi 16Gi

Chiama Google Cloud o i servizi online nel codice Python

Una funzione definita dall'utente Python accede a un servizio Google Cloud o a un servizio esterno utilizzando il account di servizio della connessione alle risorse Cloud. Al account di servizio della connessione devono essere concesse le autorizzazioni per accedere al servizio. Le autorizzazioni richieste variano a seconda del servizio a cui si accede e delle API chiamate dal codice Python.

Se crei una funzione definita dall'utente Python senza utilizzare una connessione alle risorse Cloud, la funzione viene eseguita in un ambiente che blocca l'accesso alla rete. Se la funzione definita dall'utente accede ai servizi online, devi crearla con una connessione alle risorse Cloud. In caso contrario, alla funzione definita dall'utente viene impedito di accedere alla rete fino al raggiungimento di un timeout della connessione interna. Quando utilizzi una connessione alle risorse Cloud, implementa quanto segue:

  • Timeout. Quando effettui chiamate di rete all'interno della tua funzione definita dall'utente Python, includi sempre un timeout ragionevole. In questo modo, la funzione definita dall'utente non si blocca a tempo indeterminato se il servizio esterno è lento a rispondere o non è raggiungibile.

  • Utilizza la gestione degli errori. Inserisci il codice della chiamata di rete in un blocco try...except per gestire correttamente potenziali errori, come errori di connessione, timeout o codici di stato di errore HTTP. In questo modo, la funzione definita dall'utente può restituire un errore significativo o un valore di riserva anziché causare l'errore o l'interruzione della risposta della query.

L'esempio seguente mostra come accedere al servizio Cloud Translation da una funzione definita dall'utente Python. Questo esempio ha due progetti: un progetto denominato my_query_project in cui crei la funzione definita dall'utente e la connessione alle risorse Cloud e un progetto in cui esegui Cloud Translation denominato my_translate_project.

Crea una connessione alle risorse Cloud

Innanzitutto, crea una connessione alle risorse Cloud in my_query_project. Per creare la connessione alle risorse cloud, segui questi passaggi.

Seleziona una delle seguenti opzioni:

Console

  1. Vai alla pagina BigQuery.

    Vai a BigQuery

  2. Nel riquadro a sinistra, fai clic su Explorer:

    Pulsante evidenziato per il riquadro Spazio di esplorazione.

    Se non vedi il riquadro a sinistra, fai clic su Espandi riquadro sinistro per aprirlo.

  3. Nel riquadro Explorer, espandi il nome del progetto, quindi fai clic su Connessioni.

  4. Nella pagina Connessioni, fai clic su Crea connessione.

  5. In Tipo di connessione, scegli Modelli remoti di Vertex AI, funzioni remote, BigLake e Spanner (risorsa Cloud).

  6. Nel campo ID connessione, inserisci un nome per la connessione.

  7. In Tipo di località, seleziona una località per la connessione. La connessione deve essere collocata insieme alle altre risorse, ad esempio i set di dati.

  8. Fai clic su Crea connessione.

  9. Fai clic su Vai alla connessione.

  10. Nel riquadro Informazioni sulla connessione, copia l'ID account di servizio da utilizzare in un passaggio successivo.

SQL

Utilizza l'istruzione CREATE CONNECTION:

  1. Nella console Google Cloud , vai alla pagina BigQuery.

    Vai a BigQuery

  2. Nell'editor di query, inserisci la seguente istruzione:

    CREATE CONNECTION [IF NOT EXISTS] `CONNECTION_NAME`
    OPTIONS (
      connection_type = "CLOUD_RESOURCE",
      friendly_name = "FRIENDLY_NAME",
      description = "DESCRIPTION"
      );

    Sostituisci quanto segue:

    • CONNECTION_NAME: il nome della connessione nel formato PROJECT_ID.LOCATION.CONNECTION_ID, LOCATION.CONNECTION_ID o CONNECTION_ID. Se il progetto o la località vengono omessi, vengono dedotti dal progetto e dalla località in cui viene eseguita l'istruzione.
    • FRIENDLY_NAME (facoltativo): un nome descrittivo per la connessione.
    • DESCRIPTION (facoltativo): una descrizione della connessione.

  3. Fai clic su Esegui.

Per saperne di più su come eseguire le query, consulta Esegui una query interattiva.

bq

  1. In un ambiente a riga di comando, crea una connessione:

    bq mk --connection --location=REGION --project_id=PROJECT_ID \
        --connection_type=CLOUD_RESOURCE CONNECTION_ID

    Il parametro --project_id sostituisce il progetto predefinito.

    Sostituisci quanto segue:

    • REGION: la tua regione di connessione
    • PROJECT_ID: il tuo ID progetto Google Cloud
    • CONNECTION_ID: un ID per la tua connessione

    Quando crei una risorsa di connessione, BigQuery crea un account di servizio di sistema univoco e lo associa alla connessione.

    Risoluzione dei problemi: se ricevi il seguente errore di connessione, aggiorna Google Cloud SDK:

    Flags parsing error: flag --connection_type=CLOUD_RESOURCE: value should be one of...
    
  2. Recupera e copia l'ID del account di servizio da utilizzare in un passaggio successivo:

    bq show --connection PROJECT_ID.REGION.CONNECTION_ID

    L'output è simile al seguente:

    name                          properties
    1234.REGION.CONNECTION_ID     {"serviceAccountId": "connection-1234-9u56h9@gcp-sa-bigquery-condel.iam.gserviceaccount.com"}
    

Python

Prima di provare questo esempio, segui le istruzioni di configurazione di Python nella guida rapida di BigQuery per l'utilizzo delle librerie client. Per saperne di più, consulta la documentazione di riferimento dell'API BigQuery Python.

Per eseguire l'autenticazione in BigQuery, configura le Credenziali predefinite dell'applicazione. Per saperne di più, vedi Configura l'autenticazione per le librerie client.

import google.api_core.exceptions
from google.cloud import bigquery_connection_v1

client = bigquery_connection_v1.ConnectionServiceClient()


def create_connection(
    project_id: str,
    location: str,
    connection_id: str,
):
    """Creates a BigQuery connection to a Cloud Resource.

    Cloud Resource connection creates a service account which can then be
    granted access to other Google Cloud resources for federated queries.

    Args:
        project_id: The Google Cloud project ID.
        location: The location of the connection (for example, "us-central1").
        connection_id: The ID of the connection to create.
    """

    parent = client.common_location_path(project_id, location)

    connection = bigquery_connection_v1.Connection(
        friendly_name="Example Connection",
        description="A sample connection for a Cloud Resource.",
        cloud_resource=bigquery_connection_v1.CloudResourceProperties(),
    )

    try:
        created_connection = client.create_connection(
            parent=parent, connection_id=connection_id, connection=connection
        )
        print(f"Successfully created connection: {created_connection.name}")
        print(f"Friendly name: {created_connection.friendly_name}")
        print(
            f"Service Account: {created_connection.cloud_resource.service_account_id}"
        )

    except google.api_core.exceptions.AlreadyExists:
        print(f"Connection with ID '{connection_id}' already exists.")
        print("Please use a different connection ID.")
    except Exception as e:
        print(f"An unexpected error occurred while creating the connection: {e}")

Node.js

Prima di provare questo esempio, segui le istruzioni di configurazione di Node.js nella guida rapida di BigQuery per l'utilizzo delle librerie client. Per saperne di più, consulta la documentazione di riferimento dell'API BigQuery Node.js.

Per eseguire l'autenticazione in BigQuery, configura le Credenziali predefinite dell'applicazione. Per saperne di più, vedi Configura l'autenticazione per le librerie client.

const {ConnectionServiceClient} =
  require('@google-cloud/bigquery-connection').v1;
const {status} = require('@grpc/grpc-js');

const client = new ConnectionServiceClient();

/**
 * Creates a new BigQuery connection to a Cloud Resource.
 *
 * A Cloud Resource connection creates a service account that can be granted access
 * to other Google Cloud resources.
 *
 * @param {string} projectId The Google Cloud project ID. for example, 'example-project-id'
 * @param {string} location The location of the project to create the connection in. for example, 'us-central1'
 * @param {string} connectionId The ID of the connection to create. for example, 'example-connection-id'
 */
async function createConnection(projectId, location, connectionId) {
  const parent = client.locationPath(projectId, location);

  const connection = {
    friendlyName: 'Example Connection',
    description: 'A sample connection for a Cloud Resource',
    // The service account for this cloudResource will be created by the API.
    // Its ID will be available in the response.
    cloudResource: {},
  };

  const request = {
    parent,
    connectionId,
    connection,
  };

  try {
    const [response] = await client.createConnection(request);

    console.log(`Successfully created connection: ${response.name}`);
    console.log(`Friendly name: ${response.friendlyName}`);

    console.log(`Service Account: ${response.cloudResource.serviceAccountId}`);
  } catch (err) {
    if (err.code === status.ALREADY_EXISTS) {
      console.log(`Connection '${connectionId}' already exists.`);
    } else {
      console.error(`Error creating connection: ${err.message}`);
    }
  }
}

Java

Prima di provare questo esempio, segui le istruzioni di configurazione di Java nella guida rapida di BigQuery per l'utilizzo delle librerie client. Per saperne di più, consulta la documentazione di riferimento dell'API BigQuery Java.

Per eseguire l'autenticazione in BigQuery, configura le Credenziali predefinite dell'applicazione. Per saperne di più, vedi Configura l'autenticazione per le librerie client.

import com.google.api.gax.rpc.AlreadyExistsException;
import com.google.api.gax.rpc.ApiException;
import com.google.cloud.bigquery.connection.v1.CloudResourceProperties;
import com.google.cloud.bigquery.connection.v1.Connection;
import com.google.cloud.bigquery.connection.v1.CreateConnectionRequest;
import com.google.cloud.bigquery.connection.v1.LocationName;
import com.google.cloud.bigqueryconnection.v1.ConnectionServiceClient;
import java.io.IOException;

public class CreateConnection {

  /**
   * Creates a BigQuery connection to a Cloud Resource. A Cloud Resource connection provisions a
   * service account that can be granted access to other Google Cloud resources for federated
   * queries.
   *
   * @param projectId The Google Cloud project ID (for example, "example-project-id").
   * @param location The geographic location of the connection (for example, "us-central1").
   * @param connectionId The ID of the connection to create (for example, "example-connection-id").
   */
  public static void createConnection(String projectId, String location, String connectionId) {
    LocationName parent = LocationName.of(projectId, location);

    // CloudResourceProperties provisions a managed Google Cloud service account on creation.
    CloudResourceProperties cloudResourceProperties = CloudResourceProperties.newBuilder().build();
    Connection connection =
        Connection.newBuilder()
            .setFriendlyName("Example Connection")
            .setDescription("Cloud Resource connection for federated queries.")
            .setCloudResource(cloudResourceProperties)
            .build();

    CreateConnectionRequest request =
        CreateConnectionRequest.newBuilder()
            .setParent(parent.toString())
            .setConnectionId(connectionId)
            .setConnection(connection)
            .build();

    try (ConnectionServiceClient client = ConnectionServiceClient.create()) {
      Connection response = client.createConnection(request);

      System.out.printf("Successfully created connection: %s%n", response.getName());
      System.out.printf("Friendly name: %s%n", response.getFriendlyName());
      System.out.printf(
          "Service Account: %s%n", response.getCloudResource().getServiceAccountId());
    } catch (AlreadyExistsException err) {
      System.err.printf(
          "error: connection '%s' already exists in location '%s' for project '%s': %s%n",
          connectionId, location, projectId, err.getMessage());
    } catch (ApiException | IOException err) {
      System.err.printf(
          "error: failed to create connection '%s' in location '%s' for project '%s': %s%n",
          connectionId, location, projectId, err.getMessage());
    }
  }

Terraform

Utilizza la risorsa google_bigquery_connection.

Per eseguire l'autenticazione in BigQuery, configura le Credenziali predefinite dell'applicazione. Per saperne di più, vedi Configura l'autenticazione per le librerie client.

L'esempio seguente crea una connessione alle risorse Cloud denominata my_cloud_resource_connection nella regione US:


# This queries the provider for project information.
data "google_project" "default" {}

# This creates a cloud resource connection in the US region named my_cloud_resource_connection.
# Note: The cloud resource nested object has only one output field - serviceAccountId.
resource "google_bigquery_connection" "default" {
  connection_id = "my_cloud_resource_connection"
  project       = data.google_project.default.project_id
  location      = "US"
  cloud_resource {}
}

Per applicare la configurazione Terraform in un progetto Google Cloud , completa i passaggi descritti nelle sezioni seguenti.

Prepara Cloud Shell

  1. Avvia Cloud Shell.
  2. Imposta il progetto Google Cloud predefinito in cui vuoi applicare le configurazioni Terraform.

    Devi eseguire questo comando una sola volta per progetto e puoi eseguirlo in qualsiasi directory.

    export GOOGLE_CLOUD_PROJECT=PROJECT_ID

    Le variabili di ambiente vengono sostituite se imposti valori espliciti nel file di configurazione Terraform.

Prepara la directory

Ogni file di configurazione Terraform deve avere la propria directory (chiamata anche modulo principale).

  1. In Cloud Shell, crea una directory e un nuovo file al suo interno. Il nome file deve avere l'estensione .tf, ad esempio main.tf. In questo tutorial, il file è denominato main.tf.
    mkdir DIRECTORY && cd DIRECTORY && touch main.tf
  2. Se stai seguendo un tutorial, puoi copiare il codice campione in ogni sezione o passaggio.

    Copia il codice campione nel file main.tf appena creato.

    Facoltativamente, copia il codice da GitHub. Questa opzione è consigliata quando lo snippet Terraform fa parte di una soluzione end-to-end.

  3. Esamina e modifica i parametri di esempio da applicare al tuo ambiente.
  4. Salva le modifiche.
  5. Inizializza Terraform. Devi eseguire questa operazione una sola volta per directory.
    terraform init

    Facoltativamente, per utilizzare l'ultima versione del provider Google, includi l'opzione -upgrade:

    terraform init -upgrade

Applica le modifiche

  1. Esamina la configurazione e verifica che le risorse che Terraform creerà o aggiornerà corrispondano alle tue aspettative:
    terraform plan

    Apporta le correzioni necessarie alla configurazione.

  2. Applica la configurazione Terraform eseguendo il comando seguente e inserendo yes al prompt:
    terraform apply

    Attendi che Terraform visualizzi il messaggio "Apply complete!".

  3. Apri il tuo progetto Google Cloud per visualizzare i risultati. Nella console Google Cloud , vai alle risorse nell'interfaccia utente per assicurarti che Terraform le abbia create o aggiornate.

Concedi l'accesso al account di servizio della connessione

Ti servirà l'ID del account di servizio che hai copiato in precedenza quando configuri le autorizzazioni per la connessione. Quando crei una risorsa di connessione, BigQuery crea un account di servizio di sistema univoco e lo associa alla connessione.

Per concedere al account di servizio di connessione alle risorse Cloud l'accesso ai tuoi progetti, concedi al account di servizio il ruolo Service Usage Consumer (roles/serviceusage.serviceUsageConsumer) in my_query_project e il ruolo Utente API Cloud Translation (roles/cloudtranslate.user) in my_translate_project.

Console

  1. Vai alla pagina IAM.

    Vai a IAM

  2. Verifica che l'opzione my_query_project sia selezionata.

  3. Fai clic su Concedi l'accesso.

  4. Nel campo Nuove entità, inserisci l'ID account di servizio della connessione alle risorse Cloud che hai copiato in precedenza.

  5. Nel campo Seleziona un ruolo, scegli Utilizzo del servizio, quindi seleziona Utilizzatore Service Usage.

  6. Fai clic su Salva.

  7. Nel selettore di progetti, scegli my_translate_project.

  8. Vai alla pagina IAM.

    Vai a IAM

  9. Fai clic su Concedi l'accesso.

  10. Nel campo Nuove entità, inserisci l'ID account di servizio della connessione alle risorse Cloud che hai copiato in precedenza.

  11. Nel campo Seleziona un ruolo, scegli Cloud Translation e poi seleziona Utente API Cloud Translation.

  12. Fai clic su Salva.

SQL

Utilizza l'istruzione GRANT per concedere il ruolo Service Usage Consumer (roles/serviceusage.serviceUsageConsumer) al account di servizio in my_query_project:

  1. Nella console Google Cloud , vai alla pagina BigQuery.

    Vai a BigQuery

  2. Nell'editor di query, inserisci la seguente istruzione:

      GRANT `roles/serviceusage.serviceUsageConsumer`
      ON PROJECT `my_query_project`
      TO "connection:SERVICE_ACCOUNT_ID";
      

    Sostituisci SERVICE_ACCOUNT_ID con l'ID del service account che hai copiato in precedenza.

  3. Fai clic su Esegui.

Per saperne di più su come eseguire le query, consulta Esegui una query interattiva.

Utilizza l'istruzione GRANT per concedere il ruolo Cloud Translation API User (roles/cloudtranslate.user) in my_translate_project:

  1. Nella console Google Cloud , vai alla pagina BigQuery.

    Vai a BigQuery

  2. Nell'editor di query, inserisci la seguente istruzione:

      GRANT `roles/cloudtranslate.user`
      ON PROJECT `my_translate_project`
      TO "connection:SERVICE_ACCOUNT_ID";
      

    Sostituisci SERVICE_ACCOUNT_ID con l'ID del service account che hai copiato in precedenza.

  3. Fai clic su Esegui.

Per saperne di più su come eseguire le query, consulta Esegui una query interattiva.

Crea una funzione definita dall'utente Python che chiama il servizio Cloud Translation

In my_query_project, crea una funzione definita dall'utente Python che chiama il servizio Cloud Translation utilizzando la connessione alle risorse Cloud.

  1. Nella console Google Cloud , vai alla pagina BigQuery.

    Vai a BigQuery

  2. Inserisci la seguente istruzione CREATE FUNCTION nell'editor di query:

    CREATE FUNCTION `PROJECT_ID.DATASET_ID`.translate_to_es(x 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"""
    
    from google.api_core.retry import Retry
    from google.cloud import translate
    
    project = "my_translate_project"
    translate_client = translate.TranslationServiceClient()
    
    def do_translate(x : str) -> str:
    
        response = translate_client.translate_text(
            request={
                "parent": f"projects/PROJECT_ID/locations/us-central1",
                "contents": [x],
                "target_language_code": "es",
                "mime_type": "text/plain",
            },
            retry=Retry(),
        )
        return response.translations[0].translated_text
    
    """;
    
    -- Call the UDF.
    WITH text_table AS
      (SELECT "Hello" AS text
      UNION ALL
      SELECT "Good morning" AS text
      UNION ALL
      SELECT "Goodbye" AS text)
    SELECT text,
    `PROJECT_ID.DATASET_ID`.translate_to_es(text) AS translated_text
    FROM text_table;

    Sostituisci quanto segue:

    • PROJECT_ID: l'ID progetto
    • DATASET_ID: l'ID del set di dati.
    • REGION: la regione della connessione.
    • CONNECTION_ID: l'ID connessione.
  3. Fai clic su  Esegui.

    L'output dovrebbe essere simile all'esempio seguente:

    +--------------------------+-------------------------------+
    | text                     | translated_text               |
    +--------------------------+-------------------------------+
    | Hello                    | Hola                          |
    | Good morning             | Buen dia                      |
    | Goodbye                  | Adios                         |
    +--------------------------+-------------------------------+
    

Utilizza i Controlli di servizio VPC

Le funzioni definite dall'utente Python ereditano il perimetro dei Controlli di servizio VPC del progetto che esegue il job di query. Questo perimetro protegge i job dall'esfiltrazione di dati e garantisce che le interazioni con i servizi siano sicure.

Quando richiami una funzione definita dall'utente Python all'interno del perimetro dei Controlli di servizio VPC, la connettività di rete è la seguente:

  • Le UDF Python che non utilizzano una connessione alle risorse Cloud sono completamente isolate. Tutto il traffico in uscita è bloccato.
  • Le funzioni definite dall'utente Python che utilizzano una connessione alle risorse Cloud non possono accedere a internet pubblico. Le funzioni definite dall'utente Python possono accedere solo ai servizi Google Cloud che supportano i Controlli di servizio VPC. Il traffico in uscita verso qualsiasi destinazione diversa da restricted.googleapis.com viene bloccato.

Configura le funzioni definite dall'utente Python per accedere ai servizi Google Cloud in modo sicuro all'interno dei Controlli di servizio VPC

Per accedere ai servizi Google Cloud dalle funzioni definite dall'utente Python applicando i Controlli di servizio VPC, segui questi passaggi:

  1. Crea la funzione definita dall'utente Python utilizzando la clausola WITH CONNECTION dell'istruzione CREATE FUNCTION.
  2. Includi nel perimetro di servizio il progetto BigQuery in cui viene eseguito il job di query e il progetto di servizio di destinazione. In alternativa, configura un bridge del perimetro.
  3. Aggiungi l'API del servizio di destinazione alla configurazione del perimetro. Ad esempio, translate.googleapis.com se ti connetti all'API Cloud Translation.

Per maggiori dettagli sulla configurazione di un perimetro dei Controlli di servizio VPC, consulta:

Utilizza il logging

Quando abiliti il logging, puoi visualizzare i log in tempo reale generati dalle tue funzioni definite dall'utente Python in Cloud Logging per identificare e risolvere i problemi nel tuo codice. Per evitare l'esfiltrazione accidentale dei dati, il logging delle funzioni definite dall'utente Python è disattivato per impostazione predefinita.

Abilita il logging

Per attivare il logging per la sessione, esegui la seguente istruzione prima di eseguire la query:

SET @@udf.properties = JSON '{"enableDebugOutput": true}';

Per registrare le informazioni, utilizza le funzioni della libreria Python logging, ad esempio logging.info o logging.error. La funzione print() non è supportata.

I log vengono scritti nella risorsa bigquery.googleapis.com/ManagedRoutineInvocation in Logging, che ha le seguenti etichette disponibili per il filtro:

  • resource_container: l'ID del progetto in cui è stato eseguito il job di query.
  • location: la località in cui è stato eseguito il job di query.
  • query_job_id: l'ID del job di query che ha richiamato la funzione definita dall'utente Python.
  • routine_project_id: l'ID progetto in cui è archiviata la routine richiamata.
  • routine_dataset_id: l'ID del set di dati in cui è archiviata la routine richiamata.
  • routine_id: l'ID della routine richiamata.

I dati registrati in Cloud Logging sono soggetti ai prezzi di Google Cloud Observability.

Esempio

L'esempio seguente mostra come utilizzare il logging per eseguire il debug degli errori in una funzione definita dall'utente Python senza causare l'errore della query.

La funzione definita dall'utente Python extract_user_email estrae gli indirizzi email dalle stringhe JSON. Poiché un'eccezione non gestita in una funzione definita dall'utente può causare l'errore di un'intera query, la funzione rileva le eccezioni e restituisce None, che diventa un valore NULL in BigQuery. Per aiutarti a identificare gli input non validi che non è stato possibile analizzare, la funzione registra in modo selettivo il payload problematico in Cloud Logging:

CREATE OR REPLACE FUNCTION `PROJECT_ID.DATASET_ID`.extract_user_email(payload STRING)
RETURNS STRING
LANGUAGE python
OPTIONS (entry_point='parse_email', runtime_version='python-3.11')
AS
r"""
import json
import logging
def parse_email(payload):
  try:
    # Attempt to parse the JSON and extract the email
    data = json.loads(payload)
    return data.get('email')
  except Exception as e:
    # Log the exact bad data and the error to Cloud Logging
    logging.info(f"Failed to parse payload: '{payload}'. Error: {e}")
    # Return None (NULL in BigQuery) to prevent the query from failing.
    return None
""";

-- The query completes successfully, returning NULL for the invalid row.
-- The info log for 'corrupted_payload_string' is sent to Cloud Logging.
SET @@udf.properties = JSON '{"enableDebugOutput": true}';
SELECT `PROJECT_ID.DATASET_ID`.extract_user_email(raw_data) AS email
FROM UNNEST([
    '{"email": "cloudysanfrancisco@gmail.com", "event": "click"}',
    'corrupted_payload_string',
    '{"email": "baklavainthebalkans@gmail.com", "event": "view"}'
]) AS raw_data;

I log che contengono l'input corrupted_payload_string sono accessibili in Logging.

Visualizza i log

Per visualizzare i log delle funzioni definite dall'utente Python, scegli una delle opzioni nelle sezioni seguenti.

Informazioni job

Per visualizzare i log delle funzioni definite dall'utente Python per un job di query dalla scheda Informazioni sul job, segui questi passaggi:

  1. Nel riquadro Risultati delle query, fai clic sulla scheda Informazioni job.

  2. Nel campo Log, fai clic su Log. Si apre Esplora log, precompilato con una query che mostra i log per la chiamata della funzione definita dall'utente Python.

Esplora log

Puoi anche andare direttamente a Esplora log e creare una query per visualizzare i log delle funzioni definite dall'utente Python:

  1. Vai alla pagina Esplora log di Cloud Logging.

    Vai a Esplora log

  2. Nell'editor di query, crea una query utilizzando il tipo di risorsa bigquery.googleapis.com/ManagedRoutineInvocation e le etichette delle risorse pertinenti. Ad esempio, puoi utilizzare la seguente query per visualizzare i log delle funzioni definite dall'utente Python provenienti da un job di query:

    resource.type="bigquery.googleapis.com/ManagedRoutineInvocation"
    resource.labels.query_job_id="QUERY_JOB_ID"
    

    Sostituisci QUERY_JOB_ID con l'ID del job di query che ha richiamato la funzione definita dall'utente Python.

Visualizza le metriche delle funzioni definite dall'utente Python

Le funzioni definite dall'utente Python esportano le metriche in Cloud Monitoring. Queste metriche ti aiutano a monitorare vari aspetti dell'integrità operativa e del consumo di risorse della funzione definita dall'utente, fornendo informazioni sulle prestazioni e sul comportamento delle istanze della funzione definita dall'utente.

Tipo di risorsa monitorata

Le metriche per le funzioni definite dall'utente Python sono riportate nel seguente tipo di risorsa Cloud Monitoring:

  • Tipo: bigquery.googleapis.com/ManagedRoutineInvocation
  • Nome visualizzato: BigQuery Managed Routine Invocation
  • Etichette:
    • resource_container: l'ID del progetto in cui è stato eseguito il job di query.
    • location: la località in cui è stato eseguito il job di query.
    • query_job_id: l'ID del job di query che ha richiamato la funzione definita dall'utente Python.
    • routine_project_id: l'ID progetto in cui è archiviata la routine richiamata.
    • routine_dataset_id: l'ID del set di dati in cui è archiviata la routine richiamata.
    • routine_id: l'ID della routine richiamata.

Metriche

Per il tipo di risorsa bigquery.googleapis.com/ManagedRoutineInvocation sono disponibili le seguenti metriche:

Metrica Descrizione Unità Tipo di valore
bigquery.googleapis.com/managed_routine/python/cpu_utilizations Quando viene richiamata una funzione definita dall'utente Python, questa metrica mostra la distribuzione dell'utilizzo della CPU in tutte le istanze della funzione definita dall'utente Python per il job di query. Un valore percentuale DISTRIBUTION
bigquery.googleapis.com/managed_routine/python/memory_utilizations Quando viene richiamata una funzione definita dall'utente Python, questa metrica mostra la distribuzione dell'utilizzo della memoria in tutte le istanze della funzione definita dall'utente Python per il job di query. Un valore percentuale DISTRIBUTION
bigquery.googleapis.com/managed_routine/python/max_request_concurrencies Questa metrica mostra la distribuzione del numero massimo di richieste in parallelo gestite da ogni istanza di funzione definita dall'utente Python. Conteggio DISTRIBUTION

Visualizza metriche

Per visualizzare le metriche per le funzioni definite dall'utente Python, scegli una delle opzioni nelle sezioni seguenti.

Dettagli job

Per visualizzare le metriche delle funzioni definite dall'utente di Python per un job di query specifico, segui questi passaggi:

  1. Vai alla pagina BigQuery.

    Vai a BigQuery

  2. Fai clic su Cronologia job.

  3. Nella colonna ID job, fai clic sull'ID job della query.

  4. Nella pagina Dettagli job di query, fai clic su Dashboard di Cloud Monitoring. Questo link mostra una dashboard filtrata per mostrare le metriche della funzione definita dall'utente Python per il job.

Esplora metriche

Per visualizzare le metriche delle funzioni definite dall'utente Python in Metrics Explorer, segui questi passaggi:

  1. Vai alla pagina Esplora metriche di Cloud Monitoring.

    Vai a Esplora metriche

  2. Fai clic su Seleziona una metrica e, nel campo Filtro, digita BigQuery Managed Routine Invocation o bigquery.googleapis.com/ManagedRoutineInvocation.

  3. Scegli Routine gestita di BigQuery > Managed_routine.

  4. Fai clic su una delle metriche disponibili, ad esempio:

    • Utilizzo della CPU dell'istanza
    • Utilizzo della memoria dell'istanza
    • Numero max richieste in parallelo
  5. Fai clic su Applica.

    Per impostazione predefinita, le metriche vengono visualizzate in un grafico.

  6. Puoi filtrare e raggruppare le metriche utilizzando le etichette definite nei tipi di risorse monitorate. Per filtrare le metriche:

    1. Nel campo Filtro, scegli un tipo di risorsa, ad esempio query_job_id o routine_id.

    2. Nel campo Valore, inserisci l'ID job o l'ID routine oppure scegline uno dall'elenco.

Dashboard di Cloud Monitoring

Per visualizzare le metriche delle funzioni definite dall'utente Python utilizzando le dashboard di monitoraggio, segui questi passaggi:

  1. Vai alla pagina Dashboard di Cloud Monitoring.

    Vai a Dashboard

  2. Fai clic sulla dashboard BigQuery Managed Routine Query Monitoring.

    Questa dashboard fornisce una panoramica delle metriche chiave delle tue funzioni definite dall'utente.

  3. Per filtrare questa dashboard:

    1. Fai clic su Filtro.

    2. Nell'elenco Filtra per risorsa, scegli un'opzione come ID progetto, località, ID routine o ID job.

Best practice

Quando crei funzioni definite dall'utente in Python, segui queste best practice:

  • Ottimizza la logica delle query per il raggruppamento in batch. Le strutture di query complesse possono disattivare il raggruppamento in batch. Questo impone un'elaborazione lenta, riga per riga, che aumenta notevolmente la latenza su set di dati di grandi dimensioni.
  • Ottimizza il payload dei dati. Le dimensioni delle singole righe possono influire sull'efficienza della funzionalità di raggruppamento in batch. Mantieni ogni riga il più piccola possibile per massimizzare il numero di righe che possono essere elaborate in un singolo batch.
  • Configura i limiti dei container in modo efficiente. La scalabilità è una funzione della CPU, della memoria e della contemporaneità delle richieste. Controlla le metriche di monitoraggio per ottimizzare la configurazione del container. Se l'utilizzo della CPU è elevato, aumenta l'allocazione della CPU utilizzando il limite container_cpu o riduci la contemporaneità delle richieste dei container utilizzando il limite container_request_concurrency.
  • Quando utilizzi l'ottimizzazione iterativa, inizia con i valori predefiniti. Se le prestazioni non sono ottimali, analizza le metriche di monitoraggio per identificare colli di bottiglia specifici.
  • Implementa i timeout delle API. Quando la funzione definita dall'utente Python accede a internet, imposta un timeout per la chiamata API per evitare comportamenti imprevisti. Un esempio di accesso a internet è la lettura da un bucket Cloud Storage.
  • Per ridurre i costi e migliorare la leggibilità, limita il logging alle eccezioni, alle anomalie dei dati o a finestre di debug specifiche.

Località supportate

Le funzioni definite dall'utente Python sono supportate in tutte le località multiregionali e regionali di BigQuery.

Prezzi

I costi delle funzioni definite dall'utente Python vengono fatturati utilizzando lo SKU dei servizi BigQuery.

Gli addebiti includono:

  • Creazione o ricreazione dell'immagine container della funzione definita dall'utente. Questo addebito è proporzionale alla durata necessaria per creare l'immagine corrispondente con il codice e le dipendenze del cliente.

    • Se utilizzi l'API Routines, la durata dell'ultima build si trova nel campo BuildStatus. Puoi anche visualizzare la durata della build nella colonna BuildStatus nella vista INFORMATION_SCHEMA.ROUTINES.
    • Per visualizzare il costo totale delle build per progetto, puoi filtrare il report sulla fatturazione utilizzando quanto segue:
      • Chiave: goog-bq-feature-type
      • Valore: MANAGED_ROUTINE_BUILD
  • Ai clienti che utilizzano le funzioni definite dall'utente Python viene addebitato anche il costo della chiamata di una funzione definita dall'utente Python. Questo addebito è proporzionale alla quantità di risorse di calcolo e memoria consumate quando viene richiamata la funzione definita dall'utente Python.

    • Per visualizzare i costi delle UDF Python per query, puoi eseguire una query sul campo ExternalServiceCosts utilizzando l'API Job. Puoi anche visualizzare i costi per query visualizzando la colonna external_service_costs nella vista INFORMATION_SCHEMA.JOBS e applicando il seguente filtro: 'external_service_costs.external_service="MANAGED_ROUTINE_EXECUTION"'.
    • Per visualizzare il costo totale dell'esecuzione delle UDF Python per progetto, puoi filtrare il report sulla fatturazione utilizzando quanto segue:
      • Chiave: goog-bq-feature-type
      • Valore: MANAGED_ROUTINE_EXECUTION
  • Se le funzioni definite dall'utente Python generano traffico in uscita verso una rete esterna o internet, vedrai anche un addebito per il traffico in uscita verso internet di livello Premium in base agli SKU BigQuery Egress.

Quote

Consulta Quote e limiti delle funzioni definite dall'utente.