Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.
CREATE EXTERNAL FUNCTION
Crea una funzione scalare definita dall'utente (UDF) basata su Amazon AWS Lambda Redshift. Per ulteriori informazioni sulle funzioni Lambda definite dall'utente, consultare Lambda scalare UDFs.
Privilegi richiesti
Di seguito sono riportati i privilegi necessari per CREATE EXTERNAL FUNCTION:
-
Superuser
-
Utenti con il privilegio CREATE [ OR REPLACE ] EXTERNAL FUNCTION
Sintassi
CREATE [ OR REPLACE ] EXTERNAL FUNCTION external_fn_name ( [data_type] [, ...] ) RETURNS data_type { VOLATILE | STABLE } LAMBDA 'lambda_fn_name' IAM_ROLE { default | ‘arn:aws:iam::
<Account AWS-id>
:role/<role-name>
’ RETRY_TIMEOUT milliseconds MAX_BATCH_ROWS count MAX_BATCH_SIZE size [ KB | MB ];
Parametri
- OR REPLACE
-
Una clausola che specifica che se una funzione con stesso nome e tipi di dati degli argomenti di input o firma è già esistente, la funzione esistente viene sostituita. Puoi sostituire una funzione solo con una nuova funzione che definisce un set identico di tipi di dati. Devi essere un utente con privilegi avanzati per sostituire una funzione.
Se definisci una funzione con lo stesso nome di una funzione esistente ma con una firma diversa, viene creata una nuova funzione. In altre parole, il nome della funzione è sottoposto a overload. Per ulteriori informazioni, consulta Overload dei nomi delle funzioni.
- external_fn_name
-
Il nome della funzione esterna. Se si specifica un nome schema (come myschema.myfunction), la funzione viene creata utilizzando lo schema specificato. Altrimenti, la funzione viene creata nello schema corrente. Per ulteriori informazioni sui nomi validi, consultare Nomi e identificatori.
Consigliamo di assegnare un prefisso
f_
ai nomi di tutte le funzioni definite dall'utente. Amazon Redshift riserva il prefissof_
per i nomi delle funzioni definite dall'utente. Utilizzando il prefissof_
, è possibile assicurarsi che il nome della funzione non sia in conflitto con i nomi delle funzioni SQL predefinite di Amazon Redshift correnti e future. Per ulteriori informazioni, consulta Prevenzione dei conflitti di denominazione delle funzioni definite dall'utente. - data_type
-
Il tipo di dati per gli argomenti di input. Per ulteriori informazioni, consultare Python scalare UDFs e Lambda scalare UDFs.
- RETURNS data_type
-
Il tipo di dati del valore restituito dalla funzione. Il tipo di dati RETURNS può essere qualsiasi tipo di dati standard Amazon Redshift. Per ulteriori informazioni, consultare Python scalare UDFs e Lambda scalare UDFs.
- VOLATILE | STABILE
-
Informa l'ottimizzatore di query circa la volatilità della funzione.
Per ottenere la migliore ottimizzazione, etichettare la funzione con la categoria di volatilità più rigida valida. In ordine di rigidità, a partire dalla meno rigida, le categorie di volatilità sono le seguenti:
-
VOLATILE
-
STABLE
VOLATILE
Dati gli stessi argomenti, la funzione può restituire risultati diversi su chiamate successive, anche per le righe in una singola istruzione. L'ottimizzatore di query non può fare alcuna ipotesi sul comportamento di una funzione volatile. Una query che utilizza una funzione volatile deve rivalutare la funzione per ogni input.
STABLE
Dati gli stessi argomenti, la funzione è garantita per restituire gli stessi risultati nelle chiamate successive elaborate all'interno di una singola istruzione. La funzione può restituire risultati diversi se richiamati in istruzioni diverse. Questa categoria consente all'ottimizzatore di ridurre il numero di volte in cui la funzione viene chiamata all'interno di una singola istruzione.
Nota che se la severità scelta non è valida per la funzione, c'è il rischio che l'ottimizzatore salti alcune chiamate in base a questa severità. Ciò può comportare un set di risultati errato.
La clausola IMMUTABLE non è attualmente supportata per Lambda. UDFs
-
- LAMBDA 'lambda_fn_name'
-
Il nome della funzione richiamata da Amazon Redshift.
Per i passaggi per creare una AWS Lambda funzione, consulta Creare una funzione Lambda con la console nella Guida per gli AWS Lambda sviluppatori.
Per informazioni sulle autorizzazioni richieste per la funzione Lambda, consultare Autorizzazioni AWS Lambda nella Guida per gli sviluppatori di AWS Lambda .
- IAM_ROLE {default | 'arn:aws:iam: :role/ '
<Account AWS-id>
<role-name>
-
Utilizzare la parola chiave predefinita per fare in modo che Amazon Redshift utilizzi il ruolo IAM impostato come predefinito e associato al cluster quando viene eseguito il comando CREATE EXTERNAL FUNCTION.
L'Amazon Resource Name (ARN) per un ruolo IAM utilizzato dal cluster per l'autenticazione e l'autorizzazione. Il comando CREATE EXTERNAL FUNCTION è autorizzato per il richiamo delle funzioni Lambda tramite questo ruolo IAM. Se il cluster possiede un ruolo IAM esistente con autorizzazioni per richiamare funzioni Lambda collegate, è possibile sostituire l'ARN del ruolo. Per ulteriori informazioni, consulta Configurazione del parametro di autorizzazione per Lambda UDFs.
Di seguito è mostrata la sintassi del parametro IAM_ROLE.
IAM_ROLE 'arn:aws:iam::aws-account-id:role/role-name'
- RETRY_TIMEOUT millisecondi
-
La quantità di tempo totale, espressa in millisecondi, utilizzata da Amazon Redshift per i ritardi nei backoff dei tentativi.
Invece di riprovare immediatamente per eventuali query non riuscite, Amazon Redshift esegue i backoff e attende un certo periodo di tempo tra i tentativi. Quindi Amazon Redshift riprova la richiesta di eseguire nuovamente la query non riuscita fino a quando la somma di tutti i ritardi è uguale o superiore al valore RETRY_TIMEOUT specificato. Il valore di default è 20.000 millisecondi.
Quando viene richiamata una funzione Lambda, Amazon Redshift prova a eseguire nuovamente le query che ricevono errori come
TooManyRequestsException
,EC2ThrottledException
eServiceException
.È possibile impostare il parametro RETRY_TIMEOUT su 0 millisecondi per evitare nuovi tentativi per una funzione Lambda definita dall'utente.
- MAX_BATCH_ROWS count
-
Numero massimo di righe che Amazon Redshift invia in una singola richiesta batch per una singola chiamata lambda.
Il valore minimo per questo parametro è 1. Il valore massimo è INT_MAX o 2.147.483.647.
Questo parametro è facoltativo. Il valore predefinito è INT_MAX o 2.147.483.647.
- MAX_BATCH_SIZE size [ KB | MB ]
-
La dimensione massima del payload di dati che Amazon Redshift invia in una singola richiesta batch per una singola chiamata lambda.
Il valore minimo per questo parametro è 1 KB. Il valore massimo è 5 MB.
Il valore predefinito di questo parametro è 5 MB.
KB e MB sono facoltativi. Se non si imposta l'unità di misura, Amazon Redshift utilizza per impostazione predefinita KB.
Note per l'utilizzo
Considera quanto segue quando crei UDFs Lambda:
-
L'ordine delle chiamate alla funzione Lambda sugli argomenti di input non è fisso o garantito. Può variare tra le istanze di esecuzione delle query, a seconda della configurazione del cluster.
-
Non è garantito che le funzioni vengano applicate a ciascun argomento di input una sola volta. L'interazione tra Amazon Redshift e AWS Lambda potrebbe portare a chiamate ripetitive con gli stessi input.
Esempi
Di seguito sono riportati alcuni esempi di utilizzo delle funzioni scalari definite dall'utente Lambda (). UDFs
Esempio di funzione Lambda definita dall'utente scalare che utilizza una funzione Lambda Node.js
L'esempio seguente crea una funzione esterna denominata exfunc_sum
che utilizza due numeri interi come argomenti di input. Questa funzione restituisce la somma come output intero. Il nome della funzione Lambda da chiamare è lambda_sum
. La lingua utilizzata per questa funzione Lambda è Node.js 12.x. Assicurarsi di specificare il ruolo IAM. L'esempio utilizza 'arn:aws:iam::123456789012:user/johndoe'
come ruolo IAM.
CREATE EXTERNAL FUNCTION exfunc_sum(INT,INT) RETURNS INT VOLATILE LAMBDA 'lambda_sum' IAM_ROLE 'arn:aws:iam::123456789012:role/Redshift-Exfunc-Test';
La funzione Lambda accetta il payload della richiesta ed esegue l'iterazione su ogni riga. Tutti i valori di una singola riga vengono aggiunti per calcolare la somma per quella riga, che viene salvata nell'array di risposte. Il numero di righe nell'array dei risultati è simile al numero di righe ricevute nel payload della richiesta.
Perché sia riconosciuto dalla funzione esterna, il payload della risposta JSON deve avere i dati di risultato nel campo 'results'. Il campo argomenti nella richiesta inviata alla funzione Lambda contiene il payload dei dati. In caso di richiesta batch, è possibile avere più righe nel payload dei dati. La seguente funzione Lambda itera su tutte le righe nel payload dei dati della richiesta. Inoltre, itera individualmente su tutti i valori all'interno di una singola riga.
exports.handler = async (event) => { // The 'arguments' field in the request sent to the Lambda function contains the data payload. var t1 = event['arguments']; // 'len(t1)' represents the number of rows in the request payload. // The number of results in the response payload should be the same as the number of rows received. const resp = new Array(t1.length); // Iterating over all the rows in the request payload. for (const [i, x] of t1.entries()) { var sum = 0; // Iterating over all the values in a single row. for (const y of x) { sum = sum + y; } resp[i] = sum; } // The 'results' field should contain the results of the lambda call. const response = { results: resp }; return JSON.stringify(response); };
Nell'esempio seguente viene chiamata la funzione esterna con valori letterali.
select exfunc_sum(1,2); exfunc_sum ------------ 3 (1 row)
Nell'esempio seguente viene creata una tabella denominata t_sum con due colonne, c1 e c2, del tipo di dati intero e vengono inserite due righe di dati. Quindi la funzione esterna viene chiamata passando i nomi delle colonne di questa tabella. Le due righe della tabella vengono inviate in una richiesta batch nel payload della richiesta come un singolo richiamo Lambda.
CREATE TABLE t_sum(c1 int, c2 int); INSERT INTO t_sum VALUES (4,5), (6,7); SELECT exfunc_sum(c1,c2) FROM t_sum; exfunc_sum --------------- 9 13 (2 rows)
Esempio di funzione Lambda definita dall'utente scalare che utilizza l'attributo RETRY_TIMEOUT
Nella sezione seguente, puoi trovare un esempio di come utilizzare l'attributo RETRY_TIMEOUT in Lambda. UDFs
AWS Lambda le funzioni hanno limiti di concorrenza che è possibile impostare per ciascuna funzione. Per ulteriori informazioni sui limiti di concorrenza, consulta Gestire la concorrenza per una funzione Lambda nella Guida per gli AWS Lambda sviluppatori e il post Managing AWS Lambda Function Concurrency
Quando il numero di richieste servite da una funzione Lambda definita dall'utente supera i limiti di simultaneità, le nuove richieste ricevono l'errore TooManyRequestsException
. La funzione Lambda definita dall'utente riprova su questo errore fino a quando la somma di tutti i ritardi tra le richieste inviate alla funzione Lambda è uguale o superiore al valore RETRY_TIMEOUT impostato. Il valore di default di RETRY_TIMEOUT è 20.000 millisecondi.
L'esempio seguente crea una funzione Lambda denominata exfunc_sleep_3
. Questa funzione prende in carico il payload della richiesta, itera su ogni riga e converte l'input in maiuscolo. Quindi si interrompe per 3 secondi e restituisce il risultato. Il linguaggio utilizzato per questa funzione Lambda è Python 3.8.
Il numero di righe nell'array dei risultati è simile al numero di righe ricevute nel payload della richiesta. Perché sia riconosciuto dalla funzione esterna, il payload della risposta JSON deve avere i dati di risultato nel campo results
. Il campo arguments
nella richiesta inviata alla funzione Lambda contiene il payload dei dati. In caso di richiesta batch, è possibile avere più righe nel payload dei dati.
Il limite di simultaneità per questa funzione è impostato specificatamente su 1 nella simultaneità riservata per dimostrare l'utilizzo dell'attributo RETRY_TIMEOUT. Quando l'attributo è impostato su 1, la funzione Lambda può servire solo una richiesta alla volta.
import json import time def lambda_handler(event, context): t1 = event['arguments'] # 'len(t1)' represents the number of rows in the request payload. # The number of results in the response payload should be the same as the number of rows received. resp = [None]*len(t1) # Iterating over all rows in the request payload. for i, x in enumerate(t1): # Iterating over all the values in a single row. for j, y in enumerate(x): resp[i] = y.upper() time.sleep(3) ret = dict() ret['results'] = resp ret_json = json.dumps(ret) return ret_json
Di seguito, due esempi aggiuntivi illustrano l'attributo RETRY_TIMEOUT. Ognuno di essi richiama una singola funzione Lambda definita dall'utente. Durante il richiamo della funzione Lambda, ogni esempio esegue la stessa query SQL per richiamare la funzione Lambda da due sessioni di database simultanee contemporaneamente. Quando la prima query che richiama la funzione Lambda definita dall'utente viene servita dalla funzione, la seconda query riceve l'errore TooManyRequestsException
. Questo risultato si verifica perché si imposta in modo specifico la simultaneità riservata nella funzione definita dall'utente su 1. Per informazioni su come configurare la simultaneità riservata per le funzioni Lambda, consultare Configurazione della simultaneità riservata.
Nel primo esempio che segue, l'attributo RETRY_TIMEOUT per la funzione Lambda definita dall'utente viene impostato su 0 millisecondi. Se la richiesta Lambda riceve una qualsiasi eccezione dalla funzione Lambda, Amazon Redshift non esegue alcun nuovo tentativo. Questo risultato si verifica perché l'attributo RETRY_TIMEOUT è impostato su 0.
CREATE OR REPLACE EXTERNAL FUNCTION exfunc_upper(varchar) RETURNS varchar VOLATILE LAMBDA 'exfunc_sleep_3' IAM_ROLE 'arn:aws:iam::123456789012:role/Redshift-Exfunc-Test' RETRY_TIMEOUT 0;
Con RETRY_TIMEOUT impostato su 0, è possibile eseguire le seguenti due query da sessioni di database separate e visualizzare risultati diversi.
La prima query SQL che utilizza la funzione Lambda definita dall'utente viene eseguita correttamente.
select exfunc_upper('Varchar'); exfunc_upper -------------- VARCHAR (1 row)
La seconda query, eseguita contemporaneamente da una sessione di database separata, riceve l'errore TooManyRequestsException
.
select exfunc_upper('Varchar'); ERROR: Rate Exceeded.; Exception: TooManyRequestsException; ShouldRetry: 1 DETAIL: ----------------------------------------------- error: Rate Exceeded.; Exception: TooManyRequestsException; ShouldRetry: 1 code: 32103 context:query: 0 location: exfunc_client.cpp:102 process: padbmaster [pid=26384] -----------------------------------------------
Nel primo esempio che segue, l'attributo RETRY_TIMEOUT per la funzione Lambda definita dall'utente viene impostato su 3.000 millisecondi. Anche se la seconda query viene eseguita contemporaneamente, la funzione Lambda definita dall'utente tenta di nuovo fino a quando il ritardo totale è di 3.000 millisecondi. Pertanto, entrambe le query vengono eseguite correttamente.
CREATE OR REPLACE EXTERNAL FUNCTION exfunc_upper(varchar) RETURNS varchar VOLATILE LAMBDA 'exfunc_sleep_3' IAM_ROLE 'arn:aws:iam::123456789012:role/Redshift-Exfunc-Test' RETRY_TIMEOUT 3000;
Con RETRY_TIMEOUT impostato su 3.000 millisecondi, è possibile eseguire le seguenti due query da sessioni di database separate e visualizzare gli stessi risultati.
La prima query SQL che esegue la funzione Lambda definita dall'utente viene eseguita correttamente.
select exfunc_upper('Varchar'); exfunc_upper -------------- VARCHAR (1 row)
La seconda query viene eseguita contemporaneamente e la funzione Lambda definita dall'utente prova di nuovo fino a quando il ritardo totale è di 3.000 millisecondi.
select exfunc_upper('Varchar'); exfunc_upper -------------- VARCHAR (1 row)
Esempio di funzione Lambda definita dall'utente scalare che utilizza una funzione Lambda Python
L'esempio seguente crea una funzione esterna denominata exfunc_multiplication
e che moltiplica i numeri e restituisce un numero intero. Questo esempio incorpora il successo e i campi error_msg
nella risposta Lambda. Il campo di successo è impostato su false quando c'è un overflow di numeri interi nel risultato della moltiplicazione e il messaggio error_msg
è impostato su Integer multiplication overflow
. La funzione exfunc_multiplication
accetta tre numeri interi come argomenti di input e restituisce la somma come output intero.
Il nome della funzione Lambda richiamata è lambda_multiplication
. Il linguaggio utilizzato per questa funzione Lambda è Python 3.8. Assicurarsi di specificare il ruolo IAM.
CREATE EXTERNAL FUNCTION exfunc_multiplication(int, int, int) RETURNS INT VOLATILE LAMBDA 'lambda_multiplication' IAM_ROLE 'arn:aws:iam::123456789012:role/Redshift-Exfunc-Test';
La funzione Lambda accetta il payload della richiesta ed esegue l'iterazione su ogni riga. Tutti i valori di una singola riga vengono moltiplicati per calcolare il risultato di tale riga, che viene salvato nell'elenco delle risposte. In questo esempio viene utilizzato un valore di successo booleano impostato su true per impostazione predefinita. Se il risultato della moltiplicazione per una riga ha un overflow intero, il valore di successo è impostato su false. Quindi il ciclo di iterazione si interrompe.
Durante la creazione del payload di risposta, se il valore di successo è false, la seguente funzione Lambda aggiunge il campo error_msg
nel payload. Imposta anche il messaggio di errore su Integer multiplication overflow
. Se il valore di successo è true, i dati dei risultati vengono aggiunti nel campo dei risultati. Il numero di righe nell'array dei risultati, se presente, è simile al numero di righe ricevute nel payload della richiesta.
Il campo argomenti nella richiesta inviata alla funzione Lambda contiene il payload dei dati. In caso di richiesta batch, è possibile avere più righe nel payload dei dati. La seguente funzione Lambda itera su tutte le righe nel payload dei dati richiesta e itera individualmente su tutti i valori all'interno di una singola riga.
import json def lambda_handler(event, context): t1 = event['arguments'] # 'len(t1)' represents the number of rows in the request payload. # The number of results in the response payload should be the same as the number of rows received. resp = [None]*len(t1) # By default success is set to 'True'. success = True # Iterating over all rows in the request payload. for i, x in enumerate(t1): mul = 1 # Iterating over all the values in a single row. for j, y in enumerate(x): mul = mul*y # Check integer overflow. if (mul >= 9223372036854775807 or mul <= -9223372036854775808): success = False break else: resp[i] = mul ret = dict() ret['success'] = success if not success: ret['error_msg'] = "Integer multiplication overflow" else: ret['results'] = resp ret_json = json.dumps(ret) return ret_json
Nell'esempio seguente viene chiamata la funzione esterna con valori letterali.
SELECT exfunc_multiplication(8, 9, 2); exfunc_multiplication --------------------------- 144 (1 row)
Nell'esempio seguente viene creata una tabella denominata t_multi con tre colonne, c1, c2 e c3, del tipo di dati intero. La funzione esterna viene chiamata passando i nomi delle colonne di questa tabella. I dati vengono inseriti in modo tale da causare l'overflow di interi per mostrare come l'errore viene propagato.
CREATE TABLE t_multi (c1 int, c2 int, c3 int); INSERT INTO t_multi VALUES (2147483647, 2147483647, 4); SELECT exfunc_multiplication(c1, c2, c3) FROM t_multi; DETAIL: ----------------------------------------------- error: Integer multiplication overflow code: 32004context: context: query: 38 location: exfunc_data.cpp:276 process: query2_16_38 [pid=30494] -----------------------------------------------