Utiliser des fonctions définies par l'utilisateur en Python

Une fonction définie par l'utilisateur (UDF) Python vous permet d'implémenter une fonction scalaire en Python et de l'utiliser dans une requête SQL. Les UDF Python sont semblables aux UDF SQL et JavaScript, mais avec des fonctionnalités supplémentaires. Les UDF Python vous permettent d'installer des bibliothèques tierces à partir de l'index de packages Python (PyPI) et d'accéder à des services externes à l'aide d'une connexion aux ressources Cloud.

Les fonctions définies par l'utilisateur en Python sont créées et exécutées sur des ressources gérées par BigQuery.

Limites

  • python-3.11 est le seul environnement d'exécution compatible.
  • Vous ne pouvez pas créer d'UDF Python temporaire.
  • Vous ne pouvez pas utiliser de fonction définie par l'utilisateur Python avec une vue matérialisée.
  • Les résultats d'une requête qui appelle une UDF Python ne sont pas mis en cache, car la valeur renvoyée par une UDF Python est toujours considérée comme non déterministe.
  • Assured Workloads n'est pas compatible.
  • Les types de données suivants ne sont pas acceptés : JSON, RANGE, INTERVAL et GEOGRAPHY.
  • Les conteneurs qui exécutent des fonctions définies par l'utilisateur Python ne peuvent être configurés que jusqu'à 4 processeurs virtuels et 16 Gio.
  • Le chiffrement du code des UDF Python avec des clés de chiffrement gérées par le client (CMEK) n'est pas possible.
  • Les fonctions définies par l'utilisateur en Python sont compatibles avec VPC Service Controls, mais pas avec les réseaux VPC.

Rôles requis

Les rôles IAM requis varient selon que vous êtes propriétaire ou utilisateur de la fonction Python définie par l'utilisateur.

Propriétaires d'UDF

Le propriétaire d'une UDF Python crée ou met à jour une UDF. Des rôles supplémentaires sont également requis si vous créez une UDF Python qui référence une connexion aux ressources Cloud. Cette connexion n'est requise que si votre UDF utilise la clause WITH CONNECTION pour accéder à un service externe.

Pour obtenir les autorisations nécessaires pour créer ou mettre à jour une UDF Python, demandez à votre administrateur de vous accorder les rôles IAM suivants :

Pour en savoir plus sur l'attribution de rôles, consultez Gérer l'accès aux projets, aux dossiers et aux organisations.

Ces rôles prédéfinis contiennent les autorisations requises pour créer ou mettre à jour une UDF Python. Pour connaître les autorisations exactes requises, développez la section Autorisations requises :

Autorisations requises

Les autorisations suivantes sont requises pour créer ou mettre à jour une UDF Python :

  • Créez une UDF Python à l'aide de l'instruction CREATE FUNCTION : bigquery.routines.create sur l'ensemble de données.
  • Mettez à jour une UDF Python à l'aide de l'instruction CREATE FUNCTION : bigquery.routines.update sur l'ensemble de données.
  • Exécuter un job de requête d'instruction CREATE FUNCTION : bigquery.jobs.create sur le projet
  • Créer une connexion à une ressource cloud : bigquery.connections.create sur le projet
  • Utiliser une connexion dans l'instruction CREATE FUNCTION : bigquery.connections.delegate sur la connexion

Vous pouvez également obtenir ces autorisations avec des rôles personnalisés ou d'autres rôles prédéfinis.

Pour en savoir plus sur les rôles dans BigQuery, consultez Rôles IAM prédéfinis.

Utilisateurs de fonctions UDF;utilisateur

Un utilisateur d'UDF Python appelle une UDF créée par quelqu'un d'autre. Des rôles supplémentaires sont également requis si vous appelez une UDF Python qui fait référence à une connexion aux ressources Cloud.

Pour obtenir les autorisations nécessaires pour appeler une UDF Python créée par un autre utilisateur, demandez à votre administrateur de vous accorder les rôles IAM suivants :

Pour en savoir plus sur l'attribution de rôles, consultez Gérer l'accès aux projets, aux dossiers et aux organisations.

Ces rôles prédéfinis contiennent les autorisations requises pour appeler une UDF Python créée par un autre utilisateur. Pour connaître les autorisations exactes requises, développez la section Autorisations requises :

Autorisations requises

Les autorisations suivantes sont requises pour appeler une UDF Python créée par un autre utilisateur :

  • Pour exécuter un job de requête qui référence une UDF Python : bigquery.jobs.create sur le projet
  • Pour appeler une UDF Python créée par quelqu'un d'autre : bigquery.routines.get sur l'ensemble de données
  • Pour exécuter une UDF Python qui référence une connexion à une ressource cloud : bigquery.connections.use sur la connexion

Vous pouvez également obtenir ces autorisations avec des rôles personnalisés ou d'autres rôles prédéfinis.

Pour en savoir plus sur les rôles dans BigQuery, consultez Rôles IAM prédéfinis.

Créer une UDF Python persistante

Suivez ces règles lorsque vous créez une UDF Python :

  • Le corps de la fonction Python définie par l'utilisateur doit être une chaîne littérale entre guillemets représentant le code Python. Pour en savoir plus sur les littéraux de chaîne entre guillemets, consultez Formats des littéraux entre guillemets.

  • Le corps de la fonction Python définie par l'utilisateur doit inclure une fonction Python utilisée dans l'argument entry_point de la liste d'options de la fonction Python définie par l'utilisateur.

  • Une version de l'environnement d'exécution Python doit être spécifiée dans l'option runtime_version. La seule version d'exécution Python compatible est python-3.11. Pour obtenir la liste complète des options disponibles, consultez la liste des options de fonction pour l'instruction CREATE FUNCTION.

Pour créer une fonction Python persistante définie par l'utilisateur, utilisez l'instruction CREATE FUNCTION sans le mot clé TEMP ou TEMPORARY. Pour supprimer une fonction Python persistante définie par l'utilisateur, utilisez l'instruction DROP FUNCTION.

Exemple

Pour voir un exemple de création d'une fonction Python persistante définie par l'utilisateur, choisissez l'une des options suivantes :

Console

L'exemple suivant crée une fonction Python persistante définie par l'utilisateur nommée multiplyInputs et l&#UDF;appelle à partir d'une instruction SELECT :

  1. Accédez à la page BigQuery.

    Accéder à BigQuery

  2. Dans l'éditeur de requête, saisissez l'instruction CREATE FUNCTION suivante :

    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;

    Remplacez PROJECT_ID.DATASET_ID par l'ID de votre projet et l'ID de votre ensemble de données.

  3. Cliquez sur  Exécuter.

    Cet exemple génère la sortie suivante :

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

BigQuery DataFrames

L'exemple suivant utilise BigQuery DataFrames pour transformer une fonction personnalisée en fonction définie par l'utilisateur 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}")

État de la compilation du conteneur

Lorsque vous créez une UDF Python à l'aide de l'instruction CREATE FUNCTION, BigQuery crée ou met à jour une image de conteneur basée sur une image de base. Le conteneur est créé sur l'image de base à l'aide de votre code et des dépendances de package spécifiées.

La création du conteneur est un processus de longue durée. La première requête après l'exécution de l'instruction CREATE FUNCTION attend que la compilation de l'image soit terminée. En l'absence de dépendances externes, l'image de conteneur est généralement créée en moins d'une minute.

La taille de tous les conteneurs de fonctions définies par l'utilisateur Python par projet et par région est limitée à un total de 10 Gio. Pour en savoir plus, consultez Limites des fonctions définies par l'utilisateur pour les UDF persistantes. La compilation de votre conteneur échoue si votre projet a atteint le quota.

Pour afficher l'état de la compilation de votre conteneur, choisissez l'une des options suivantes :

Console

  1. Accédez à la page Studio de BigQuery.

    Accéder à Studio

  2. Dans le volet de gauche, développez votre projet, puis cliquez sur Ensembles de données.

  3. Cliquez sur le lien pour ouvrir l'ensemble de données contenant votre UDF Python.

  4. Sur la page de l'ensemble de données, cliquez sur l'onglet Routines.

  5. Dans la colonne ID de la routine, cliquez sur votre UDF Python.

  6. Sur la page Informations sur la fonction persistante, vous pouvez consulter l'état de la compilation, sa durée et la taille de l'image. L'état de la compilation est l'un des suivants :

    • En cours
    • Réussi
    • Échec

    Si une compilation échoue, la page d'informations sur la fonction fournit des messages d'erreur détaillés pour vous aider à résoudre les problèmes, tels que les erreurs de syntaxe ou les problèmes d'installation de packages externes.

    Page "Informations sur la fonction persistante" dans la console.

SQL

Pour interroger les champs d'état de compilation dans la vue INFORMATION_SCHEMA.ROUTINES, procédez comme suit :

  1. Accédez à la page Studio de BigQuery.

    Accéder à Studio

  2. Accédez à l'éditeur de requête ou cliquez sur Requête SQL.

  3. Saisissez la requête suivante pour récupérer les champs BUILD_STATUS de la vue INFORMATION_SCHEMA.ROUTINES. La colonne BUILD_STATUS est de type STRUCT en GoogleSQL :

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

    Remplacez PROJECT_ID.DATASET_ID par l'ID de votre projet et l'ID de votre ensemble de données.

    Le résultat doit se présenter sous la forme suivante. Les champs d'erreur sont omis :

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

API

Affichez l'état de compilation du conteneur à l'aide de RoutineBuildStatus dans l'API.

Créer une UDF Python vectorisée

Vous pouvez implémenter votre UDF Python pour traiter un lot de lignes au lieu d'une seule ligne à l'aide de la vectorisation. La vectorisation peut améliorer les performances des requêtes. Vous pouvez créer une UDF vectorisée à l'aide de Pandas ou d'Apache Arrow.

Pour contrôler le comportement du traitement par lot, spécifiez le nombre maximal de lignes dans chaque lot à l'aide de l'option max_batching_rows dans la liste d'options CREATE OR REPLACE FUNCTION. Si vous spécifiez max_batching_rows, BigQuery détermine le nombre de lignes d'un lot, jusqu'à la limite max_batching_rows. Si max_batching_rows n'est pas spécifié, le nombre de lignes à traiter par lot est déterminé automatiquement.

Utiliser Pandas

Une UDF Python vectorisée comporte un seul argument pandas.DataFrame qui doit être annoté. L'argument pandas.DataFrame comporte le même nombre de colonnes que les paramètres de la fonction définie par l'utilisateur (UDF) Python définis dans l'instruction CREATE FUNCTION. Les noms de colonnes de l'argument pandas.DataFrame sont identiques à ceux des paramètres de la UDF'utilisateur.

Votre fonction doit renvoyer un pandas.Series ou un pandas.DataFrame à une seule colonne avec le même nombre de lignes que l'entrée.

L'exemple suivant crée une UDF Python vectorisée nommée multiplyInputs avec deux paramètres : x et y.

  1. Accédez à la page BigQuery.

    Accéder à BigQuery

  2. Dans l'éditeur de requête, saisissez l'instruction CREATE FUNCTION suivante :

    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']
    
    ''';

    Remplacez PROJECT_ID.DATASET_ID par l'ID de votre projet et l'ID de votre ensemble de données.

    L'appel de la UDF est identique à celui de l'exemple précédent.

  3. Cliquez sur  Exécuter.

Utiliser Apache Arrow

L'exemple suivant utilise l'interface RecordBatch d'Apache Arrow. Lorsque vous utilisez l'interface RecordBatch, la fonction transmet un lot de lignes de colonnes de longueur égale au point d'entrée. L'exemple suivant utilise Apache Arrow pour créer une UDF Python vectorisée nommée multiplyVectorizedArrow.

  1. Accédez à la page BigQuery.

    Accéder à BigQuery

  2. Dans l'éditeur de requête, saisissez l'instruction CREATE FUNCTION suivante :

    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)
    ''';

    Remplacez PROJECT_ID.DATASET_ID par l'ID de votre projet et l'ID de votre ensemble de données.

    L'appel de la UDF est identique à celui des exemples précédents.

  3. Cliquez sur  Exécuter.

Appeler une fonction Python définie par l'utilisateur

Si vous êtes autorisé à appeler une UDF Python, vous pouvez l'appeler comme n'importe quelle autre fonction. Pour utiliser une fonction définie dans un autre projet, utilisez le nom complet de la fonction. Par exemple, pour appeler une fonction d'extraction XML nommée cw_xml_extract dans un autre projet, procédez comme suit.

Console

  1. Accédez à la page BigQuery.

    Accéder à BigQuery

  2. Dans l'éditeur de requête, saisissez l'exemple suivant :

    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. Cliquez sur  Exécuter.

    Cet exemple génère la sortie suivante :

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

BigQuery DataFrames

L'exemple suivant utilise les méthodes sql_scalar, read_gbq_function et apply de BigQuery DataFrames pour appeler une UDF 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")

Types de données compatibles avec les fonctions Python définies par l'utilisateur

Le tableau suivant définit le mappage entre les types de données BigQuery, les types de données Python et les types de données Pandas :

Type de données BigQuery Type de données intégré Python utilisé par l'UDF standard Type de données Pandas utilisé par l'UDF vectorisée Type de données PyArrow utilisé pour ARRAY et STRUCT dans une UDF vectorisée
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

Paramètre de fonction : datetime.datetime (avec le fuseau horaire UTC défini)

Valeur renvoyée par la fonction : datetime.datetime (avec n'importe quel fuseau horaire défini)

Paramètre de fonction : timestamp[us, tz=UTC][pyarrow]

Valeur renvoyée par la fonction : timestamp[us, tz=*][pyarrow]\(any timezone\)

TimestampType(timestamp[us]), avec fuseau horaire
DATE datetime.date date32[pyarrow] DataType(date32[day])
TIME datetime.time time64[pyarrow] Time64Type(time64[us])
DATETIME datetime.datetime (sans fuseau horaire) timestamp[us][pyarrow] TimestampType(timestamp[us]), sans fuseau horaire
ARRAY list list<...>[pyarrow], où le type de données de l'élément est un pandas.ArrowDtype ListType
STRUCT dict struct<...>[pyarrow], où le type de données du champ est pandas.ArrowDtype StructType

Versions d'exécution compatibles

Les UDF Python BigQuery sont compatibles avec l'environnement d'exécution python-3.11. Cette version de Python inclut des packages préinstallés supplémentaires. Pour les bibliothèques système, vérifiez l'image de base de l'environnement d'exécution.

Version d'exécution Version Python Inclut
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

Utiliser des packages tiers

Vous pouvez utiliser la liste d'options CREATE FUNCTION pour utiliser des modules autres que ceux fournis par la bibliothèque standard Python et les packages préinstallés. Vous pouvez installer des packages à partir de l'index de packages Python (PyPI) ou importer des fichiers Python depuis Cloud Storage.

Installer un package à partir de l'index de packages Python

Lorsque vous installez un package, vous devez fournir son nom. Vous pouvez éventuellement fournir sa version à l'aide des spécificateurs de version de package Python.

Si le package se trouve dans l'environnement d'exécution, il est utilisé, sauf si une version particulière est spécifiée dans la liste d'options CREATE FUNCTION. Si aucune version de package n'est spécifiée et que le package ne se trouve pas dans l'environnement d'exécution, la dernière version disponible est utilisée. Seuls les packages au format binaire wheels sont acceptés.

L'exemple suivant montre comment créer une UDF Python qui installe le package scipy à l'aide de la liste d'options CREATE OR REPLACE FUNCTION :

  1. Accédez à la page BigQuery.

    Accéder à BigQuery

  2. Dans l'éditeur de requête, saisissez l'instruction CREATE FUNCTION suivante :

    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);

    Remplacez PROJECT_ID.DATASET_ID par l'ID de votre projet et l'ID de votre ensemble de données.

  3. Cliquez sur  Exécuter.

Importer des fichiers Python supplémentaires en tant que bibliothèques

Vous pouvez étendre vos fonctions Python définies par l'utilisateur à l'aide de la liste d'options de fonction en important des fichiers Python depuis Cloud Storage.

Dans le code Python de votre UDF, vous pouvez importer les fichiers Python depuis Cloud Storage en tant que modules à l'aide de l'instruction d'importation suivie du chemin d'accès à l'objet Cloud Storage. Par exemple, si vous importez gs://BUCKET_NAME/path/to/lib1.py, votre instruction d'importation sera import path.to.lib1.

Le nom du fichier Python doit être un identifiant Python. Chaque nom folder du nom de l'objet (après /) doit être un identifiant Python valide. Dans la plage ASCII (U+0001..U+007F), les caractères suivants peuvent être utilisés dans les identifiants :

  • Lettres majuscules et minuscules de A à Z.
  • Traits de soulignement
  • Les chiffres de zéro à neuf, mais un chiffre ne peut pas apparaître comme premier caractère de l'identifiant.

L'exemple suivant montre comment créer une UDF Python qui importe le package de la bibliothèque cliente lib1.py à partir d'un bucket Cloud Storage nommé my_bucket :

  1. Accédez à la page BigQuery.

    Accéder à BigQuery

  2. Dans l'éditeur de requête, saisissez l'instruction CREATE FUNCTION suivante :

    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);
    
    """;

    Remplacez les éléments suivants :

    • PROJECT_ID : ID de votre projet.
    • DATASET_ID : ID de votre ensemble de données.
    • BUCKET_NAME : nom du bucket Cloud Storage contenant lib1.py.
    • PATH : chemin d'accès au bucket Cloud Storage.
  3. Cliquez sur  Exécuter.

Configurer les limites de conteneur pour les UDF Python

Vous pouvez utiliser la liste d'options CREATE FUNCTION pour spécifier les limites de simultanéité des requêtes de processeur, de mémoire et de conteneur pour les conteneurs qui exécutent des fonctions Python définies par l'utilisateur.

Par défaut, les ressources suivantes sont allouées aux conteneurs :

  • La mémoire allouée est de 512Mi.
  • Le processeur alloué est de 1.0 vCPU.
  • La limite de simultanéité des requêtes de conteneur est de 80.

L'exemple suivant crée une UDF Python à l'aide de la liste d'options CREATE FUNCTION pour spécifier les limites du conteneur :

  1. Accédez à la page BigQuery.

    Accéder à BigQuery

  2. Dans l'éditeur de requête, saisissez l'instruction CREATE FUNCTION suivante :

    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);

    Remplacez les éléments suivants :

    • PROJECT_ID.DATASET_ID : ID de votre projet et ID de votre ensemble de données.
    • CONTAINER_MEMORY : valeur de mémoire au format suivant : <integer_number><unit>. L'unité doit être l'une des valeurs suivantes : Mi (Mio), M (Mo), Gi (Gio) ou G (Go). Par exemple, 2Gi.
    • CONTAINER_CPU : valeur du processeur. Les fonctions définies par l'utilisateur en Python acceptent les valeurs de processeur fractionnaires comprises entre 0.33 et 1.0, ainsi que les valeurs de processeur non fractionnaires de 1, 2 et 4.
    • CONTAINER_REQUEST_CONCURRENCY : nombre maximal de requêtes simultanées par instance de conteneur de fonction Python définie par l'utilisateur. La valeur doit être un entier compris entre 1 et 1000.
  3. Cliquez sur  Exécuter.

Valeurs de processeur compatibles

Les fonctions Python définies par l'utilisateur sont compatibles avec les valeurs de processeur fractionnaires comprises entre 0.33 et 1.0, et les valeurs de processeur non fractionnaires de 1, 2 et 4. Les conteneurs qui exécutent des UDF Python peuvent être configurés avec jusqu'à 4 vCPU. La valeur par défaut est 1.0. Les valeurs d'entrée fractionnaires sont arrondies à deux décimales avant d'être appliquées au conteneur.

Valeurs de mémoire acceptées

Les conteneurs de fonctions Python définies par l'utilisateur acceptent les valeurs de mémoire au format suivant : <integer_number><unit>. L'unité doit correspondre à l'une des valeurs suivantes : Mi, M, Gi, G. La quantité de mémoire minimale que vous pouvez configurer est de 256Mi. La quantité maximale de mémoire que vous pouvez configurer est de 16Gi.

En fonction de la valeur de mémoire que vous choisissez, vous devez également spécifier une quantité de processeur appropriée. Le tableau suivant indique les valeurs de processeur minimales et maximales pour chaque valeur de mémoire :

Mémoire Processeur minimum Processeur maximal
De 256Mi à 512Mi 0.33 2
Supérieur à 512Mi et inférieur ou égal à 1Gi 0.5 2
Supérieur à 1Gi et inférieur à 2Gi 1 2
De 2Gi à 4Gi 1 4
Supérieur à 4Gi et jusqu'à 8Gi 2 4
Supérieur à 8Gi et jusqu'à 16Gi 4 4

Si vous avez déterminé la quantité de processeur que vous allouez, vous pouvez également utiliser le tableau suivant pour déterminer la plage de mémoire appropriée :

Processeur Mémoire minimale Taille maximale de la mémoire
Moins de 0.5 256Mi 512Mi
0.5 à moins de 1 256Mi 1Gi
1 256Mi 4Gi
2 256Mi 8Gi
4 2Gi 16Gi

Appeler Google Cloud ou des services en ligne dans du code Python

Une UDF Python accède à un service Google Cloud ou à un service externe à l'aide du compte de service de la connexion aux ressources Cloud. Le compte de service de la connexion doit disposer des autorisations nécessaires pour accéder au service. Les autorisations requises varient en fonction du service auquel vous accédez et des API appelées à partir de votre code Python.

Si vous créez une UDF Python sans utiliser de connexion aux ressources Cloud, la fonction est exécutée dans un environnement qui bloque l'accès au réseau. Si votre UDF accède à des services en ligne, vous devez la créer avec une connexion aux ressources Cloud. Sinon, l'UDF ne peut pas accéder au réseau tant qu'un délai avant expiration de la connexion interne n'est pas atteint. Lorsque vous utilisez une connexion à une ressource cloud, implémentez les éléments suivants :

  • Délais avant expiration. Lorsque vous effectuez des appels réseau dans votre UDF Python, incluez toujours un délai avant expiration raisonnable. Cela empêche la UDF de se bloquer indéfiniment si le service externe est lent à répondre ou inaccessible.

  • Utiliser la gestion des exceptions Encapsulez le code de votre appel réseau dans un bloc try...except pour gérer correctement les erreurs potentielles, telles que les erreurs de connexion, les délais avant expiration ou les codes d'état d'échec HTTP. Cela permet à votre UDF de renvoyer une erreur significative ou une valeur de remplacement au lieu de provoquer l'échec de la requête ou de l'empêcher de répondre.

L'exemple suivant montre comment accéder au service Cloud Translation à partir d'une UDF Python. Cet exemple comporte deux projets : un projet nommé my_query_project dans lequel vous créez la fonction définie par l&#UDF et la connexion aux ressources Cloud, et un projet dans lequel vous exécutez Cloud Translation, nommé my_translate_project.

Créer une connexion aux ressources Cloud

Tout d'abord, vous créez une connexion aux ressources Cloud dans my_query_project. Pour créer la connexion aux ressources cloud, procédez comme suit.

Sélectionnez l'une des options suivantes :

Console

  1. Accédez à la page BigQuery.

    Accéder à BigQuery

  2. Dans le volet de gauche, cliquez sur Explorateur :

    Bouton du volet Explorateur mis en évidence.

    Si le volet de gauche ne s'affiche pas, cliquez sur Développer le volet de gauche pour l'ouvrir.

  3. Dans le volet Explorateur, développez le nom de votre projet, puis cliquez sur Connexions.

  4. Sur la page Connexions, cliquez sur Créer une connexion.

  5. Dans le champ Type de connexion, sélectionnez Modèles distants Vertex AI, fonctions à distance, BigLake et Spanner (Ressource cloud).

  6. Dans le champ ID de connexion, saisissez un nom pour votre connexion.

  7. Dans le champ Type d'emplacement, sélectionnez un emplacement pour votre connexion. La connexion doit être colocalisée avec vos autres ressources, telles que les ensembles de données.

  8. Cliquez sur Créer une connexion.

  9. Cliquez sur Accéder à la connexion.

  10. Dans le volet Informations de connexion, copiez l'ID du compte de service à utiliser à l'étape suivante.

SQL

Utilisez l'instruction CREATE CONNECTION :

  1. Dans la console Google Cloud , accédez à la page BigQuery.

    Accéder à BigQuery

  2. Dans l'éditeur de requête, saisissez l'instruction suivante :

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

    Remplacez les éléments suivants :

    • CONNECTION_NAME : nom de la connexion au format PROJECT_ID.LOCATION.CONNECTION_ID, LOCATION.CONNECTION_ID ou CONNECTION_ID. Si le projet ou l'emplacement sont omis, ils sont déduits du projet et de l'emplacement où l'instruction est exécutée.
    • FRIENDLY_NAME (facultatif) : nom descriptif de la connexion.
    • DESCRIPTION (facultatif) : description de la connexion.

  3. Cliquez sur Exécuter.

Pour en savoir plus sur l'exécution des requêtes, consultez Exécuter une requête interactive.

bq

  1. Dans un environnement de ligne de commande, créez une connexion :

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

    Le paramètre --project_id remplace le projet par défaut.

    Remplacez les éléments suivants :

    • REGION : votre région de connexion
    • PROJECT_ID : ID de votre projet Google Cloud
    • CONNECTION_ID : ID de votre connexion

    Lorsque vous créez une ressource de connexion, BigQuery crée un compte de service système unique et l'associe à la connexion.

    Dépannage : Si vous obtenez l'erreur de connexion suivante, mettez à jour le Google Cloud SDK :

    Flags parsing error: flag --connection_type=CLOUD_RESOURCE: value should be one of...
    
  2. Récupérez et copiez l'ID du compte de service pour l'utiliser lors d'une prochaine étape :

    bq show --connection PROJECT_ID.REGION.CONNECTION_ID

    Le résultat ressemble à ce qui suit :

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

Python

Avant d'essayer cet exemple, suivez les instructions de configuration pour Python du guide de démarrage rapide de BigQuery : Utiliser les bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence de l'API BigQuery pour Python.

Pour vous authentifier auprès de BigQuery, configurez le service Identifiants par défaut de l'application. Pour en savoir plus, consultez la page Configurer l'authentification pour les bibliothèques clientes.

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

Avant d'essayer cet exemple, suivez les instructions de configuration pour Node.js du guide de démarrage rapide de BigQuery : Utiliser les bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence de l'API BigQuery pour Node.js.

Pour vous authentifier auprès de BigQuery, configurez le service Identifiants par défaut de l'application. Pour en savoir plus, consultez la page Configurer l'authentification pour les bibliothèques clientes.

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

Avant d'essayer cet exemple, suivez les instructions de configuration pour Java du guide de démarrage rapide de BigQuery : Utiliser les bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence de l'API BigQuery pour Java.

Pour vous authentifier auprès de BigQuery, configurez le service Identifiants par défaut de l'application. Pour en savoir plus, consultez la page Configurer l'authentification pour les bibliothèques clientes.

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

Utilisez la ressource google_bigquery_connection.

Pour vous authentifier auprès de BigQuery, configurez le service Identifiants par défaut de l'application. Pour en savoir plus, consultez la page Configurer l'authentification pour les bibliothèques clientes.

L'exemple suivant crée une connexion aux ressources Cloud nommée my_cloud_resource_connection dans la région 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 {}
}

Pour appliquer votre configuration Terraform dans un projet Google Cloud , suivez les procédures des sections suivantes.

Préparer Cloud Shell

  1. Lancez Cloud Shell.
  2. Définissez le projet Google Cloud par défaut dans lequel vous souhaitez appliquer vos configurations Terraform.

    Vous n'avez besoin d'exécuter cette commande qu'une seule fois par projet et vous pouvez l'exécuter dans n'importe quel répertoire.

    export GOOGLE_CLOUD_PROJECT=PROJECT_ID

    Les variables d'environnement sont remplacées si vous définissez des valeurs explicites dans le fichier de configuration Terraform.

Préparer le répertoire

Chaque fichier de configuration Terraform doit avoir son propre répertoire (également appelé module racine).

  1. Dans Cloud Shell, créez un répertoire et un nouveau fichier dans ce répertoire. Le nom de fichier doit comporter l'extension .tf, par exemple main.tf. Dans ce tutoriel, le fichier est appelé main.tf.
    mkdir DIRECTORY && cd DIRECTORY && touch main.tf
  2. Si vous suivez un tutoriel, vous pouvez copier l'exemple de code dans chaque section ou étape.

    Copiez l'exemple de code dans le fichier main.tf que vous venez de créer.

    Vous pouvez également copier le code depuis GitHub. Cela est recommandé lorsque l'extrait Terraform fait partie d'une solution de bout en bout.

  3. Examinez et modifiez les exemples de paramètres à appliquer à votre environnement.
  4. Enregistrez les modifications.
  5. Initialisez Terraform. Cette opération n'est à effectuer qu'une seule fois par répertoire.
    terraform init

    Vous pouvez également utiliser la dernière version du fournisseur Google en incluant l'option -upgrade :

    terraform init -upgrade

Appliquer les modifications

  1. Examinez la configuration et vérifiez que les ressources que Terraform va créer ou mettre à jour correspondent à vos attentes :
    terraform plan

    Corrigez les modifications de la configuration si nécessaire.

  2. Appliquez la configuration Terraform en exécutant la commande suivante et en saisissant yes lorsque vous y êtes invité :
    terraform apply

    Attendez que Terraform affiche le message "Apply completed!" (Application terminée).

  3. Ouvrez votre projet Google Cloud pour afficher les résultats. Dans la console Google Cloud , accédez à vos ressources dans l'interface utilisateur pour vous assurer que Terraform les a créées ou mises à jour.

Accorder l'accès au compte de service de la connexion

Vous aurez besoin de l'ID du compte de service que vous avez copié précédemment pour configurer les autorisations de la connexion. Lorsque vous créez une ressource de connexion, BigQuery crée un compte de service système unique et l'associe à la connexion.

Pour accorder au compte de service de connexion aux ressources Cloud l'accès à vos projets, attribuez-lui le rôle Consommateur Service Usage (roles/serviceusage.serviceUsageConsumer) dans my_query_project et le rôle Utilisateur de l'API Cloud Translation (roles/cloudtranslate.user) dans my_translate_project.

Console

  1. Accédez à la page IAM.

    Accéder à IAM

  2. Vérifiez que my_query_project est sélectionné.

  3. Cliquez sur Accorder l'accès.

  4. Dans le champ Nouveaux comptes principaux, saisissez l'ID du compte de service de la connexion à la ressource cloud que vous avez copié précédemment.

  5. Dans le champ Sélectionner un rôle, choisissez Service Usage, puis sélectionnez Consommateur Service Usage.

  6. Cliquez sur Enregistrer.

  7. Dans le sélecteur de projet, choisissez my_translate_project.

  8. Accédez à la page IAM.

    Accéder à IAM

  9. Cliquez sur Accorder l'accès.

  10. Dans le champ Nouveaux comptes principaux, saisissez l'ID du compte de service de la connexion à la ressource cloud que vous avez copié précédemment.

  11. Dans le champ Sélectionner un rôle, sélectionnez Cloud Translation, puis Utilisateur de l'API Cloud Translation.

  12. Cliquez sur Enregistrer.

SQL

Utilisez l'instruction GRANT pour attribuer le rôle de consommateur Service Usage (roles/serviceusage.serviceUsageConsumer) au compte de service dans my_query_project :

  1. Dans la console Google Cloud , accédez à la page BigQuery.

    Accéder à BigQuery

  2. Dans l'éditeur de requête, saisissez l'instruction suivante :

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

    Remplacez SERVICE_ACCOUNT_ID par l'ID du compte de service que vous avez copié précédemment.

  3. Cliquez sur Exécuter.

Pour en savoir plus sur l'exécution des requêtes, consultez Exécuter une requête interactive.

Utilisez l'instruction GRANT pour accorder le rôle d'utilisateur de l'API Cloud Translation (roles/cloudtranslate.user) dans my_translate_project :

  1. Dans la console Google Cloud , accédez à la page BigQuery.

    Accéder à BigQuery

  2. Dans l'éditeur de requête, saisissez l'instruction suivante :

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

    Remplacez SERVICE_ACCOUNT_ID par l'ID du compte de service que vous avez copié précédemment.

  3. Cliquez sur Exécuter.

Pour en savoir plus sur l'exécution des requêtes, consultez Exécuter une requête interactive.

Créer une UDF Python qui appelle le service Cloud Translation

Dans my_query_project, créez une UDF Python qui appelle le service Cloud Translation à l'aide de votre connexion aux ressources Cloud.

  1. Dans la console Google Cloud , accédez à la page BigQuery.

    Accéder à BigQuery

  2. Saisissez l'instruction CREATE FUNCTION suivante dans l'éditeur de requête :

    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;

    Remplacez les éléments suivants :

    • PROJECT_ID : ID du projet.
    • DATASET_ID : ID de l'ensemble de données
    • REGION : région de votre connexion.
    • CONNECTION_ID : ID de connexion.
  3. Cliquez sur  Exécuter.

    Le résultat doit se présenter sous la forme suivante :

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

Utiliser VPC Service Controls

Les fonctions définies par l'utilisateur Python héritent du périmètre VPC Service Controls du projet qui exécute le job de requête. Ce périmètre protège vos jobs contre l'exfiltration de données et garantit la sécurité des interactions entre les services.

Lorsque vous appelez une UDF Python dans le périmètre VPC Service Controls, elle dispose de la connectivité réseau suivante :

  • Les UDF Python qui n'utilisent pas de connexion aux ressources Cloud sont entièrement isolées. Tout le trafic sortant est bloqué.
  • Les UDF Python qui utilisent une connexion aux ressources Cloud sont bloquées pour l'accès à l'Internet public. Les fonctions définies par l'utilisateur en Python ne peuvent accéder qu'aux services Google Cloud compatibles avec VPC Service Controls. Le trafic sortant vers toute destination autre que restricted.googleapis.com est bloqué.

Configurer des UDF Python pour accéder aux services Google Cloud de manière sécurisée dans VPC Service Controls

Pour accéder aux services Google Cloud à partir de fonctions définies par l'utilisateur Python tout en appliquant VPC Service Controls, procédez comme suit :

  1. Créez la fonction Python définie par l'utilisateur à l'aide de la clause WITH CONNECTION de l'instruction CREATE FUNCTION.
  2. Incluez le projet BigQuery dans lequel le job de requête s'exécute et le projet de service cible dans le périmètre de service. Vous pouvez également configurer une liaison de périmètre.
  3. Ajoutez l'API du service cible à la configuration du périmètre. Par exemple, translate.googleapis.com si vous vous connectez à l'API Cloud Translation.

Pour en savoir plus sur la configuration d'un périmètre VPC Service Controls, consultez les pages suivantes :

Utiliser la journalisation

Lorsque vous activez la journalisation, vous pouvez afficher les journaux en temps réel générés par vos fonctions définies par l'utilisateur Python dans Cloud Logging pour vous aider à identifier et à résoudre les problèmes dans votre code. Pour éviter l'exfiltration accidentelle de données, la journalisation des fonctions définies par l'utilisateur Python est désactivée par défaut.

Activer la journalisation

Pour activer la journalisation pour votre session, exécutez l'instruction suivante avant d'exécuter votre requête :

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

Pour consigner des informations, utilisez les fonctions de la bibliothèque Python logging, telles que logging.info ou logging.error. La fonction print() n'est pas prise en charge.

Les journaux sont écrits dans la ressource bigquery.googleapis.com/ManagedRoutineInvocation de Logging, qui dispose des étiquettes suivantes pour le filtrage :

  • resource_container : ID du projet dans lequel le job de requête a été exécuté.
  • location : emplacement où le job de requête a été exécuté.
  • query_job_id : ID du job de requête qui a appelé l'UDF Python.
  • routine_project_id : ID du projet dans lequel la routine appelée est stockée.
  • routine_dataset_id : ID de l'ensemble de données dans lequel la routine appelée est stockée.
  • routine_id : ID de la routine appelée.

Les données consignées dans Cloud Logging sont soumises aux tarifs de Google Cloud Observability.

Exemple

L'exemple suivant montre comment utiliser la journalisation pour déboguer les erreurs dans une UDF Python sans provoquer l'échec de la requête.

La fonction Python définie par l'utilisateur extract_user_email extrait les adresses e-mail des chaînes JSON. Étant donné qu'une exception non gérée dans une UDF peut entraîner l'échec d'une requête entière, la fonction intercepte les exceptions et renvoie None, qui devient une valeur NULL dans BigQuery. Pour vous aider à identifier les entrées non valides qui n'ont pas pu être analysées, la fonction consigne de manière sélective la charge utile problématique dans 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;

Les journaux contenant l'entrée corrupted_payload_string sont accessibles dans Logging.

Afficher les journaux

Pour afficher les journaux de vos UDF Python, choisissez l'une des options des sections suivantes.

Job information

Pour afficher les journaux des UDF Python d'un job de requête à partir de l'onglet Informations sur le job, procédez comme suit :

  1. Dans le volet Résultats de la requête, cliquez sur l'onglet Informations sur le job.

  2. Dans le champ Journal, cliquez sur Journal. L'explorateur de journaux s'ouvre et est prérempli avec une requête qui affiche les journaux de votre appel de fonction Python définie par l'utilisateur.

Explorateur de journaux

Vous pouvez également accéder directement à l'explorateur de journaux et créer vous-même une requête pour afficher les journaux des UDF Python :

  1. Accédez à la page Explorateur de journaux de Cloud Logging.

    Accéder à l'explorateur de journaux

  2. Dans l'éditeur de requête, créez une requête à l'aide du type de ressource bigquery.googleapis.com/ManagedRoutineInvocation et des libellés de ressources pertinents. Par exemple, vous pouvez utiliser la requête suivante pour afficher les journaux des fonctions définies par l'utilisateur Python provenant d'un job de requête :

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

    Remplacez QUERY_JOB_ID par l'ID du job de requête qui a appelé la fonction définie par l'utilisateur Python.

Afficher les métriques des UDF Python

Les fonctions définies par l'utilisateur en Python exportent des métriques vers Cloud Monitoring. Ces métriques vous aident à surveiller divers aspects de l'état opérationnel et de la consommation de ressources de votre UDF, et fournissent des insights sur les performances et le comportement de vos instances d'UDF.

Type de ressource surveillée

Les métriques des fonctions définies par l'utilisateur Python sont consignées sous le type de ressource Cloud Monitoring suivant :

  • Type : bigquery.googleapis.com/ManagedRoutineInvocation
  • Nom à afficher : Appel de routine gérée BigQuery
  • Étiquettes :
    • resource_container : ID du projet dans lequel le job de requête a été exécuté.
    • location : emplacement où le job de requête a été exécuté.
    • query_job_id : ID du job de requête qui a appelé l'UDF Python.
    • routine_project_id : ID du projet dans lequel la routine appelée est stockée.
    • routine_dataset_id : ID de l'ensemble de données dans lequel la routine appelée est stockée.
    • routine_id : ID de la routine appelée.

Métriques

Les métriques suivantes sont disponibles pour le type de ressource bigquery.googleapis.com/ManagedRoutineInvocation :

Métrique Description Unité Type de valeur
bigquery.googleapis.com/managed_routine/python/cpu_utilizations Lorsqu'une UDF Python est appelée, cette métrique indique la répartition de l'utilisation du processeur sur toutes les instances d'UDF Python pour le job de requête. Une valeur en pourcentage DISTRIBUTION
bigquery.googleapis.com/managed_routine/python/memory_utilizations Lorsqu'une UDF Python est appelée, cette métrique indique la répartition de l'utilisation de la mémoire sur toutes les instances d'UDF Python pour le job de requête. Une valeur en pourcentage DISTRIBUTION
bigquery.googleapis.com/managed_routine/python/max_request_concurrencies Cette métrique indique la répartition du nombre maximal de requêtes simultanées traitées par chaque instance de FDU Python. Nombre DISTRIBUTION

Afficher les métriques

Pour afficher les métriques de vos UDF Python, choisissez l'une des options des sections suivantes.

Informations sur le job

Pour afficher les métriques des UDF Python pour un job de requête spécifique, procédez comme suit :

  1. Accédez à la page BigQuery.

    Accéder à BigQuery

  2. Cliquez sur Historique des jobs.

  3. Dans la colonne ID de job, cliquez sur l'ID du job de requête.

  4. Sur la page Détails du job de requête, cliquez sur Tableau de bord Cloud Monitoring. Ce lien affiche un tableau de bord filtré pour afficher les métriques de la fonction définie par l'utilisateur Python pour le job.

Explorateur de métriques

Pour afficher les métriques des UDF Python dans l'explorateur de métriques, procédez comme suit :

  1. Accédez à la page Explorateur de métriques de Cloud Monitoring.

    Accéder à l'explorateur de métriques

  2. Cliquez sur Sélectionner une métrique, puis saisissez BigQuery Managed Routine Invocation ou bigquery.googleapis.com/ManagedRoutineInvocation dans le champ Filtre.

  3. Sélectionnez Routine gérée BigQuery > Managed_routine.

  4. Cliquez sur l'une des métriques disponibles, par exemple :

    • Utilisation du processeur par l'instance
    • Utilisation de la mémoire de l'instance
    • Nombre maximal de requêtes simultanées
  5. Cliquez sur Appliquer.

    Par défaut, les métriques sont affichées dans un graphique.

  6. Vous pouvez filtrer et regrouper les métriques à l'aide des étiquettes définies dans les types de ressources Monitoring. Pour filtrer les métriques, procédez comme suit :

    1. Dans le champ Filtre, sélectionnez un type de ressource tel que query_job_id ou routine_id.

    2. Dans le champ Valeur, saisissez l'ID de job ou l'ID de routine, ou choisissez-en un dans la liste.

Tableaux de bord Cloud Monitoring

Pour afficher les métriques des FDU Python à l'aide des tableaux de bord de surveillance, procédez comme suit :

  1. Accédez à la page Tableaux de bord de Cloud Monitoring.

    Accéder à la page "Tableaux de bord"

  2. Cliquez sur le tableau de bord Surveillance des requêtes de routine gérées BigQuery.

    Ce tableau de bord fournit un aperçu des métriques clés de vos fonctions définies par l'utilisateur.

  3. Pour filtrer ce tableau de bord, procédez comme suit :

    1. Cliquez sur Filtrer.

    2. Dans la liste Filtrer par ressource, choisissez une option telle que l'ID du projet, l'emplacement, l'ID de la routine ou l'ID du job.

Bonnes pratiques

Lorsque vous créez des UDF Python, suivez ces bonnes pratiques :

  • Optimisez la logique de vos requêtes pour le traitement par lot. Les structures de requêtes complexes peuvent désactiver le traitement par lot. Cela force un traitement lent, ligne par ligne, ce qui augmente considérablement la latence sur les grands ensembles de données.
  • Optimisez la charge utile des données. La taille des lignes individuelles peut avoir un impact sur l'efficacité de la fonctionnalité de traitement par lot. Faites en sorte que chaque ligne soit aussi petite que possible afin de maximiser le nombre de lignes pouvant être traitées dans un seul lot.
  • Configurez efficacement les limites de conteneur. L'évolutivité est une fonction du processeur, de la mémoire et de la simultanéité des requêtes. Vérifiez les métriques de surveillance pour ajuster la configuration du conteneur. Si l'utilisation du processeur est élevée, augmentez l'allocation de processeur à l'aide de la limite container_cpu ou réduisez la simultanéité des requêtes de conteneur à l'aide de la limite container_request_concurrency.
  • Lorsque vous utilisez le réglage itératif, commencez par les valeurs par défaut. Si les performances ne sont pas optimales, analysez les métriques de surveillance pour identifier les goulots d'étranglement spécifiques.
  • Implémentez des délais avant expiration des API. Lorsque votre UDF Python accède à Internet, définissez un délai avant expiration pour l'appel d'API afin d'éviter tout comportement inattendu. La lecture d'un bucket Cloud Storage est un exemple d'accès à Internet.
  • Pour réduire les coûts et améliorer la lisibilité, limitez la journalisation aux exceptions, aux anomalies de données ou à des fenêtres de débogage spécifiques.

Pays acceptés

Les UDF Python sont compatibles avec tous les emplacements multirégionaux et régionaux de BigQuery.

Tarifs

Les frais liés aux fonctions définies par l'utilisateur en Python sont facturés à l'aide du SKU des services BigQuery.

Les frais incluent les éléments suivants :

  • Créer ou recréer l'image de conteneur de la UDF;utilisateur. Ces frais sont proportionnels à la durée nécessaire pour créer l'image correspondante avec le code et les dépendances du client.

    • Si vous utilisez l'API Routines, la durée de la dernière compilation se trouve dans le champ BuildStatus. Vous pouvez également afficher la durée de compilation dans la colonne BuildStatus de la vue INFORMATION_SCHEMA.ROUTINES.
    • Pour afficher le coût total des compilations par projet, vous pouvez filtrer votre rapport de facturation à l'aide des éléments suivants :
      • Key (Clé) : goog-bq-feature-type
      • Valeur : MANAGED_ROUTINE_BUILD
  • Les clients utilisant des UDF Python sont également facturés pour le coût d'appel d'une UDF Python. Ces frais sont proportionnels à la quantité de ressources de calcul et de mémoire consommées lorsque la fonction Python définie par l'utilisateur est appelée.

    • Pour afficher les coûts des UDF Python par requête, vous pouvez interroger le champ ExternalServiceCosts à l'aide de l'API Job. Vous pouvez également afficher les coûts par requête en consultant la colonne external_service_costs dans la vue INFORMATION_SCHEMA.JOBS et en appliquant le filtre suivant : 'external_service_costs.external_service="MANAGED_ROUTINE_EXECUTION"'.
    • Pour afficher le coût total d'exécution des UDF Python par projet, vous pouvez filtrer le rapport de facturation à l'aide des éléments suivants :
      • Key (Clé) : goog-bq-feature-type
      • Valeur : MANAGED_ROUTINE_EXECUTION
  • Si les UDF Python entraînent une sortie réseau externe ou Internet, des frais de sortie Internet de niveau Premium vous sont également facturés en fonction des SKU de sortie BigQuery.

Quotas

Consultez Quotas et limites des fonctions définies par l'utilisateur.