Utilizzare le funzioni remote
Una funzione remota di BigQuery ti consente di implementare la tua funzione in altri linguaggi rispetto a SQL e JavaScript o con le librerie o i servizi che non sono consentiti in BigQuery funzioni definite dall'utente.
Panoramica
Una funzione remota di BigQuery ti consente di incorporare Funzionalità GoogleSQL con software al di fuori BigQuery mediante un'integrazione diretta Cloud Functions e Cloud Run. Con funzioni remote di BigQuery, puoi eseguire il deployment Cloud Functions o Cloud Run implementato con qualsiasi per poi richiamarle da GoogleSQL query.
Flusso di lavoro
- Crea l'endpoint HTTP in Cloud Functions o Cloud Run.
- Creare una funzione remota in BigQuery.
- Crea una connessione di tipo
CLOUD_RESOURCE
. - Crea una funzione remota.
- Crea una connessione di tipo
- Utilizza la funzione remota in una query come qualsiasi altra funzione definita dall'utente.
Limitazioni
Le funzioni remote supportano solo una delle seguenti opzioni tipi di dati come argomento o tipo restituito:
- Booleano
- Byte
- Numerico
- Stringa
- Data
- Data/ora
- Ora
- Timestamp
- JSON
Le funzioni remote non supportano
ARRAY
,STRUCT
,INTERVAL
oGEOGRAPHY
tipi.Non puoi creare funzioni remote temporanee.
Non puoi creare funzioni remote con valori di tabella.
Non puoi utilizzare le funzioni remote durante la creazione di viste materializzate.
Si presume sempre che il valore restituito di una funzione remota sia non deterministico, perciò il risultato di una query che chiama una funzione remota memorizzati nella cache.
Potresti vedere richieste ripetute con gli stessi dati per il tuo endpoint, anche in seguito a risposte positive, a causa di errori di rete temporanei Errori interni di BigQuery.
Quando la valutazione di una funzione remota viene saltata per alcune righe a causa di: cortocircuito, ad esempio nelle espressioni condizionali o un'istruzione
MERGE
ConWHEN [NOT] MATCHED
, il raggruppamento in batch non viene utilizzato con la funzione remota. In questo caso, il campocalls
nel corpo della richiesta HTTP ha esattamente un elemento.Se il set di dati associato alla funzione remota viene replicato in una regione di destinazione tramite un set di dati interregionale di replica, la funzione remota può nella regione in cui è stato creato.
Creazione di un endpoint
Per creare una funzione remota in grado di implementare la logica di business, devi creare su un endpoint HTTP utilizzando Cloud Functions in Cloud Run. L'endpoint deve essere in grado di elaborare un batch di righe in una singola richiesta POST HTTP e restituiscono i risultati per il batch come Risposta HTTP.
Se stai creando la funzione remota mediante utilizzando BigQuery DataFrames, non è necessario creare manualmente l'endpoint HTTP, il servizio lo fa per automaticamente.
Consulta le Tutorial su Cloud Functions e altro Documentazione di Cloud Functions su come scrivere, eseguire il deployment, testare e gestire una Cloud Function.
Consulta le Guida rapida di Cloud Run e altra documentazione di Cloud Run su come scrivere, eseguire il deployment, testare e gestire un servizio Cloud Run.
Ti consigliamo di mantenere l'autenticazione predefinita anziché consentire una chiamata non autenticata per la tua Cloud Function dal servizio Cloud Run.
Formato di input
BigQuery invia richieste POST HTTP con corpo JSON nel seguente formato:
Nome campo | Descrizione | Tipo di campo |
---|---|---|
requestId | ID della richiesta. Univoco in più richieste inviate a questo endpoint in una query GoogleSQL. | Forniti sempre. Stringa. |
chiamante | Nome completo della risorsa del job per la query GoogleSQL che chiama la funzione remota. | Forniti sempre. Stringa. |
sessionUser | Email dell'utente che esegue la query GoogleSQL. | Forniti sempre. Stringa. |
userDefinedContext | Il contesto definito dall'utente utilizzato durante la creazione della funzione remota in BigQuery. | Facoltativo. Un oggetto JSON con coppie chiave/valore. |
chiamate | Un batch di dati di input. | Forniti sempre. Un array JSON.
Ogni elemento stesso è un array JSON, ovvero un elenco di argomenti con codifica JSON di una chiamata di funzione remota. |
Esempio di richiesta:
{
"requestId": "124ab1c",
"caller": "//bigquery.googleapis.com/projects/myproject/jobs/myproject:US.bquxjob_5b4c112c_17961fafeaf",
"sessionUser": "[email protected]",
"userDefinedContext": {
"key1": "value1",
"key2": "v2"
},
"calls": [
[null, 1, "", "abc"],
["abc", "9007199254740993", null, null]
]
}
Formato di output
BigQuery prevede che l'endpoint restituisca una risposta HTTP in il formato seguente, altrimenti BigQuery non può utilizzarlo la query chiamando la funzione remota avrà esito negativo.
Nome campo | Descrizione | Intervallo di valori |
risposte | Un gruppo di valori restituiti. | Necessario per una risposta corretta. Un array JSON.
Ogni elemento corrisponde a un valore restituito codificato JSON della funzione esterna.
Le dimensioni dell'array devono corrispondere a quelle dell'array JSON di |
errorMessage | Messaggio di errore quando viene restituito un codice di risposta HTTP diverso da 200. Per e non ripetibili, lo restituiamo come parte di BigQuery il messaggio di errore del job all'utente. | Facoltativo. Stringa. La dimensione deve essere inferiore a 1 kB. |
Esempio di risposta positiva:
{
"replies": [
1,
0
]
}
Esempio di risposta non riuscita:
{
"errorMessage": "Received but not expected that the argument 0 be null".
}
Codice di risposta HTTP
Per una risposta corretta, l'endpoint dovrebbe restituire il codice di risposta HTTP 200. Quando BigQuery riceve un qualsiasi altro valore, considera la risposta come un errore e riprova quando il codice di risposta HTTP viene 408, 429, 500, 503 o 504 fino a un limite interno.
Codifica JSON del tipo di dati SQL
Segue la codifica JSON nelle richieste/risposte HTTP la codifica JSON di BigQuery esistente per la funzione TO_JSON_STRING.
Codice della funzione Cloud Functions di esempio
Il codice Python di esempio seguente implementa l'aggiunta di tutti gli argomenti interi di la funzione remota. Gestisce una richiesta con gli argomenti per di invocazioni e restituisce tutti i risultati in una risposta.
import functions_framework
from flask import jsonify
# Max INT64 value encoded as a number in JSON by TO_JSON_STRING. Larger values are encoded as
# strings.
# See https://cloud.google.com/bigquery/docs/reference/standard-sql/json_functions#json_encodings
_MAX_LOSSLESS=9007199254740992
@functions_framework.http
def batch_add(request):
try:
return_value = []
request_json = request.get_json()
calls = request_json['calls']
for call in calls:
return_value.append(sum([int(x) if isinstance(x, str) else x for x in call if x is not None]))
replies = [str(x) if x > _MAX_LOSSLESS or x < -_MAX_LOSSLESS else x for x in return_value]
return_json = jsonify( { "replies": replies } )
return return_json
except Exception as e:
return jsonify( { "errorMessage": str(e) } ), 400
Supponendo che venga eseguito il deployment della funzione nel progetto my_gcf_project
nella regione
us-east1
come nome della funzione remote_add
, a cui è possibile accedere tramite
endpoint https://us-east1-my_gcf_project.cloudfunctions.net/remote_add
.
Esempio di codice Cloud Run
Il codice Python di esempio seguente implementa un servizio web che può essere creato e i cui deployment sono stati eseguiti in Cloud Run per la stessa funzionalità.
import os
from flask import Flask, request, jsonify
# Max INT64 value encoded as a number in JSON by TO_JSON_STRING. Larger values are encoded as
# strings.
# See https://cloud.google.com/bigquery/docs/reference/standard-sql/json_functions#json_encodings
_MAX_LOSSLESS=9007199254740992
app = Flask(__name__)
@app.route("/", methods=['POST'])
def batch_add():
try:
return_value = []
request_json = request.get_json()
calls = request_json['calls']
for call in calls:
return_value.append(sum([int(x) if isinstance(x, str) else x for x in call if x is not None]))
replies = [str(x) if x > _MAX_LOSSLESS or x < -_MAX_LOSSLESS else x for x in return_value]
return jsonify( { "replies" : replies } )
except Exception as e:
return jsonify( { "errorMessage": str(e) } ), 400
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
Consulta la guida su come creare ed eseguire il deployment del codice.
Supponendo che sia stato eseguito il deployment del servizio Cloud Run nel progetto
my_gcf_project
nella regione us-east1
come nome del servizio remote_add
, può
accessibile tramite l'endpoint
https://remote_add-<project_id_hash>-ue.a.run.app
.
Crea una funzione remota
BigQuery utilizza una connessione CLOUD_RESOURCE
per interagire con
la funzione Cloud Function. Per creare una funzione remota, è necessario
crea una connessione CLOUD_RESOURCE
. Se stai creando la funzione remota mediante
utilizzando BigQuery DataFrames
e ti è stato concesso
Amministratore IAM progetto (roles/resourcemanager.projectIamAdmin
), quindi
Non è necessario creare manualmente la connessione e concederle l'accesso; il servizio
lo fa automaticamente.
Crea una connessione
Per connetterti alla Cloud Function, devi disporre di una connessione alle risorse Cloud e Cloud Run.
Seleziona una delle seguenti opzioni:
Console
Vai alla pagina BigQuery.
Per creare una connessione, fai clic su
Aggiungi e poi fai clic su Connessioni a origini dati esterne.Nell'elenco Tipo di connessione, seleziona Modelli remoti Vertex AI, funzioni remote e BigLake (risorsa Cloud).
Nel campo ID connessione, inserisci un nome per connessione.
Fai clic su Crea connessione.
Fai clic su Vai alla connessione.
Nel riquadro Informazioni sulla connessione, copia l'ID account di servizio da utilizzare in una passaggio successivo.
bq
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
: il tuo regione di connessionePROJECT_ID
: l'ID del tuo progetto Google CloudCONNECTION_ID
: un ID per connessione
Quando crei una risorsa di connessione, BigQuery crea di 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...
Recupera e copia l'ID account di servizio per utilizzarlo in un secondo momento passaggio:
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"}
Terraform
Aggiungi la seguente sezione al tuo file main.tf
.
## This creates a cloud resource connection. ## Note: The cloud resource nested object has only one output only field - serviceAccountId. resource "google_bigquery_connection" "connection" { connection_id = "CONNECTION_ID" project = "PROJECT_ID" location = "REGION" cloud_resource {} }Sostituisci quanto segue:
CONNECTION_ID
: un ID per connessionePROJECT_ID
: l'ID del tuo progetto Google CloudREGION
: il tuo regione di connessione
Configura l'accesso
Devi concedere alla nuova connessione l'accesso in sola lettura al tuo la funzione Cloud Function o il servizio Cloud Run. Non è consigliabile consentire chiamate non autenticate per il tuo la funzione Cloud Function o il servizio Cloud Run.
Per concedere i ruoli:
Vai alla sezione IAM e Console di amministrazione.
Fai clic su
Aggiungi.Viene visualizzata la finestra di dialogo Aggiungi entità.
Nel campo Nuove entità, inserisci l'ID account di servizio che copiato in precedenza.
Nel campo Seleziona un ruolo, scegli una delle seguenti opzioni:
- Se utilizzi una Cloud Function di 1a generazione, scegli funzione Cloud Functions Functions, quindi seleziona il ruolo Invoker della funzione Cloud Functions.
- Se utilizzi una Cloud Function di seconda generazione, scegli Cloud Run, quindi seleziona il ruolo Invoker di Cloud Run.
- Se utilizzi un servizio Cloud Run, scegli Cloud Run, quindi seleziona Ruolo Invoker di Cloud Run.
Fai clic su Salva.
Crea una funzione remota
Per creare una funzione remota:
SQL
Esegui questo comando
CREATE FUNCTION
in BigQuery:
Nella console Google Cloud, vai alla pagina BigQuery.
Nell'editor query, inserisci la seguente istruzione:
CREATE FUNCTION
PROJECT_ID.DATASET_ID
.remote_add(x INT64, y INT64) RETURNS INT64 REMOTE WITH CONNECTIONPROJECT_ID.LOCATION.CONNECTION_NAME
OPTIONS ( endpoint = 'ENDPOINT_URL' )Sostituisci quanto segue:
DATASET_ID
: l'ID del tuo set di dati BigQuery.ENDPOINT_URL
: l'URL dell'endpoint della Cloud Function o della funzione remota di Cloud Run.
Fai clic su
Esegui.
Per ulteriori informazioni su come eseguire le query, vedi Eseguire una query interattiva.
DataFrame BigQuery
BigQuery DataFrames è in anteprima.
- Abilita le API richieste e assicurati che ti sia stato concesso ai ruoli richiesti, come descritto nella sezione Requisiti del Funzioni remote.
Utilizza la Decoratore
remote_function
: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 scalar # functions into a BigQuery remote function. It requires the GCP project to # be set up appropriately and the user having sufficient privileges to use # them. One can find more details about the usage and the requirements via # `help` command. help(bpd.remote_function) # Read a table and inspect the column of interest. df = bpd.read_gbq("bigquery-public-data.ml_datasets.penguins") df["body_mass_g"].head(10) # Define a custom function, and specify the intent to turn it into a remote # function. It requires a BigQuery connection. If the connection is not # already created, BigQuery DataFrames will attempt to create one assuming # the necessary APIs and IAM permissions are setup in the project. In our # examples we would be using a pre-created connection named # `bigframes-rf-conn`. We will also set `reuse=False` to make sure we don't # step over someone else creating remote function in the same project from # the exact same source code at the same time. Let's try a `pandas`-like use # case in which we want to apply a user defined scalar 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.remote_function( [float], str, bigquery_connection="bigframes-rf-conn", reuse=False, ) def get_bucket(num): if not num: return "NA" boundary = 4000 return "at_or_above_4000" if num >= boundary else "below_4000" # Then we can apply the remote function 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"]].head(10) # The above operation was possible by doing all the computation on the # cloud. For that, there is a google cloud function deployed by serializing # the user code, and a BigQuery remote function created to call the cloud # function via the latter's http endpoint on the data in the DataFrame. # The BigQuery remote function created to support the BigQuery DataFrames # remote function can be located via a property `bigframes_remote_function` # set in the remote function object. print(f"Created BQ remote function: {get_bucket.bigframes_remote_function}") # The cloud function can be located via another property # `bigframes_cloud_function` set in the remote function object. print(f"Created cloud function: {get_bucket.bigframes_cloud_function}") # Warning: The deployed cloud function may be visible to other users with # sufficient privilege in the project, so the user should be careful about # having any sensitive data in the code that will be deployed as a remote # function. # Let's continue trying other potential use cases of remote functions. 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 remote function @bpd.remote_function( [str], str, bigquery_connection="bigframes-rf-conn", reuse=False ) def get_hash(input): import hashlib # handle missing value if input is None: input = "" encoded_input = input.encode() hash = hashlib.md5(encoded_input) return hash.hexdigest() # We can use this remote function in another `pandas`-like API `map` that # can be applied on a DataFrame df_redacted = df[["species", "island", "sex"]].map(get_hash) df_redacted.head(10)
Devi avere l'autorizzazione bigquery.routines.create
sul set di dati in cui
crei la funzione remota e bigquery.connections.delegate
(disponibile nel ruolo Amministratore connessione BigQuery) per la connessione
usato dalla funzione remota.
Fornisce un contesto definito dall'utente
Puoi specificare user_defined_context
in OPTIONS
come forma di coppia chiave-valore
che faranno parte di ogni richiesta HTTP all'endpoint. Con utente
un contesto definito, è possibile creare più funzioni remote
che fornisce comportamenti diversi in base al contesto trasmesso.
Gli esempi seguenti creano due funzioni remote per criptare e decriptare
BYTES
di dati utilizzando lo stesso endpoint.
CREATE FUNCTION `PROJECT_ID.DATASET_ID`.encrypt(x BYTES)
RETURNS BYTES
REMOTE WITH CONNECTION `PROJECT_ID.LOCATION.CONNECTION_NAME`
OPTIONS (
endpoint = 'ENDPOINT_URL',
user_defined_context = [("mode", "encryption")]
)
CREATE FUNCTION `PROJECT_ID.DATASET_ID`.decrypt(x BYTES)
RETURNS BYTES
REMOTE WITH CONNECTION `PROJECT_ID.LOCATION.CONNECTION_NAME`
OPTIONS (
endpoint = 'ENDPOINT_URL',
user_defined_context = [("mode", "decryption")]
)
Limitazione del numero di righe in una richiesta batch
Puoi specificare max_batching_rows
in OPTIONS
come numero massimo di righe
in ogni richiesta HTTP, per evitare
Timeout di Cloud Functions. In caso contrario
specificato, BigQuery deciderà quante righe includere in un
batch.
Utilizza una funzione remota in una query
Assicurati di avere concesso l'autorizzazione per la tua funzione Cloud Functions, in modo che sia accessibile all'account di servizio di BigQuery associato con la connessione della funzione remota.
Devi anche avere l'autorizzazione bigquery.routines.get
per il set di dati
dove è la funzione remota e l'autorizzazione bigquery.connections.use
,
che puoi ottenere tramite il ruolo BigQuery Connection User
,
la connessione utilizzata dalla funzione remota.
Puoi utilizzare una funzione remota in una query proprio come funzione definita dall'utente.
Ad esempio, puoi utilizzare la funzione remote_add
nella query di esempio:
SELECT
val,
`PROJECT_ID.DATASET_ID`.remote_add(val, 2)
FROM
UNNEST([NULL,2,3,5,8]) AS val;
Questo esempio produce il seguente output:
+------+-----+
| val | f0_ |
+------+-----+
| NULL | 2 |
| 2 | 4 |
| 3 | 5 |
| 5 | 7 |
| 8 | 10 |
+------+-----+
Aree geografiche supportate
In BigQuery esistono due tipi di località:
Una regione è un luogo geografico ben preciso, come Londra.
Una più regioni è una grande area geografica, come gli Stati Uniti, che contiene due o più luoghi geografici.
Regioni singole
In un set di dati BigQuery a regione singola, puoi creare solo che utilizza una funzione Cloud Function di cui è stato eseguito il deployment nella stessa regione. Per esempio:
- Una funzione remota nella singola regione di BigQuery
us-east4
può usare solo una Cloud Function inus-east4
.
Pertanto, per singole regioni, le funzioni remote sono supportate solo nelle regioni che supportare sia Cloud Functions che BigQuery.
Più regioni
In un set di dati BigQuery multiregionale (US
, EU
), puoi solo
una funzione remota che utilizza una Cloud Function di cui è stato eseguito il deployment
regione all'interno di una stessa area geografica di grandi dimensioni (Stati Uniti, UE). Ad esempio:
- Una funzione remota in BigQuery
US
multiregionale può utilizzare solo una Cloud Function di cui è stato eseguito il deployment in una singola regione degli Stati Uniti area geografica, ad esempious-central1
,us-east4
,us-west2
e così via - Una funzione remota in BigQuery
EU
multiregionale può utilizzare solo di una Cloud Function di cui è stato eseguito il deployment in una singola regione stati membri di nell'Unione Europea, ad esempioeurope-north1
,europe-west3
e così via
Per saperne di più sulle regioni e multiregionali di BigQuery, consulta la pagina Località del set di dati. Per ulteriori informazioni sulle regioni di Cloud Functions, consulta Località di Cloud Functions.
Connessioni
Per una località a una o più regioni, puoi solo
crea una funzione remota nella stessa località della connessione che utilizzi. Per
Ad esempio, per creare una funzione remota nell'area multiregionale US
, utilizza una connessione
situata nell'area multiregionale US
.
Prezzi
Si applicano i prezzi di BigQuery standard.
Inoltre, potrebbero essere addebitati costi per Cloud Functions e Cloud Run utilizzando questa funzionalità. Rivedi le Cloud Functions e pagine dei prezzi di Cloud Run per maggiori dettagli.
Utilizzo dei Controlli di servizio VPC
Controlli di servizio VPC è una funzionalità di Google Cloud che consente
di configurare un perimetro sicuro per proteggersi dall'esfiltrazione di dati. Per utilizzare
Controlli di servizio VPC con funzioni remote per una maggiore sicurezza o per l'utilizzo
endpoint con internal traffic
impostazioni del traffico in entrata,
segui le
Guida ai Controlli di servizio VPC per:
Creare un perimetro di servizio.
Aggiungi nel perimetro il progetto BigQuery della query utilizzando la funzione remota.
Aggiungi il progetto dell'endpoint al perimetro e imposta
Cloud Functions API
oCloud Run API
nei servizi limitati in base al tipo di endpoint. Per ulteriori dettagli, consulta Controlli di servizio VPC di Cloud Functions e Controlli di servizio VPC di Cloud Run.
Best practice per le funzioni remote
Prefiltra l'input: se i tuoi input possono essere facilmente filtrati prima di essere trasmessi a un telecomando la query sarà probabilmente più veloce e più economica.
Mantieni scalabile la Cloud Function. La scalabilità è una funzione numero minimo di istanze, numero massimo di istanze; contemporaneità.
- Se possibile, utilizza il valore predefinito per il numero massimo di istanze della funzione Cloud Function.
- Tieni presente che non esiste un limite predefinito per le funzioni Cloud Functions HTTP di 1ª generazione. Da evitare eventi di scalabilità illimitata con Cloud Functions HTTP di 1ª generazione durante i test in produzione, ti consigliamo impostare un limite, ad esempio 3000.
Segui altri suggerimenti per la funzione Cloud Functions per migliorare le prestazioni. Le query di funzione remota che interagiscono con una Cloud Function ad alta latenza potrebbero non riuscire a causa del timeout.
Implementare il tuo endpoint per restituire un codice di risposta HTTP corretto e un payload per un risposta non riuscita.
Per ridurre al minimo i nuovi tentativi da BigQuery, utilizza i codici di risposta HTTP diversi da 408, 429, 500, 503 e 504 per una risposta non riuscita e assicurati di intercetta tutte le eccezioni nel codice della funzione. In caso contrario, il servizio HTTP può restituire automaticamente 500 per qualsiasi eccezione non rilevata. Potresti comunque vedere nuovi tentativi di richiesta HTTP quando BigQuery esegue un nuovo tentativo per una partizione dati o una query non riuscita.
L'endpoint deve restituire un payload JSON nel formato definito per un risposta non riuscita. Anche non è assolutamente obbligatorio, BigQuery riconosce se la risposta non riuscita proviene dalla tua della funzione o l'infrastruttura di Cloud Functions/Cloud Run. Quest'ultimo, BigQuery potrebbe riprovare con un limite interno diverso.
Quote
Per informazioni sulle quote per le funzioni remote, consulta Quote e limiti.