CREATE EXTERNAL FUNCTION - Amazon Redshift

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

CREATE EXTERNAL FUNCTION

Crée une fonction scalaire définie par l'utilisateur (UDF) basée sur Amazon AWS Lambda Redshift. Pour plus d’informations sur les fonctions Lambda définies par l’utilisateur, consultez Lambda scalaire UDFs.

Privilèges requis

Les privilèges suivants sont requis pour CREATE EXTERNAL FUNCTION :

  • Superuser

  • Utilisateurs disposant du EXTERNAL FUNCTION privilège CREATE [OUREPLACE]

Syntaxe

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::<Compte AWS-id>:role/<role-name>’ RETRY_TIMEOUT milliseconds MAX_BATCH_ROWS count MAX_BATCH_SIZE size [ KB | MB ];

Paramètres

OU REPLACE

Clause qui spécifie que si une fonction ayant le même nom et les mêmes types de données pour les arguments en entrée, ou signature, existe déjà, la fonction existante est remplacée. Vous pouvez uniquement remplacer une fonction par une nouvelle fonction qui définit un ensemble identique de types de données. Vous devez être un super-utilisateur pour remplacer une fonction.

Si vous définissez une fonction avec le même nom qu’une fonction existante, mais avec une signature différente, vous créez une nouvelle fonction. En d’autres termes, le nom de la fonction est surchargé. Pour plus d'informations, consultez Surcharge des noms de fonctions.

external_fn_name

Nom de la fonction externe. Si vous spécifiez un nom de schéma (tel que myschema.myfunction), la fonction est créée à l’aide du schéma spécifié. Sinon, la fonction est créée dans le schéma en cours. Pour plus d’informations sur les noms valides, consultez Noms et identificateurs.

Nous vous recommandons de préfixer tous les UDF noms parf_. Amazon Redshift réserve le f_ préfixe aux noms. UDF En utilisant le f_ préfixe, vous garantissez que votre UDF nom n'entrera en conflit avec aucun nom de SQL fonction intégré pour Amazon Redshift, aujourd'hui ou à l'avenir. Pour de plus amples informations, veuillez consulter Prévenir les conflits UDF de dénomination.

data_type

Type de données des arguments en entrée. Pour de plus amples informations, veuillez consulter Types de données.

RETURNStype_données

Type de données de la valeur renvoyée par la fonction. Le type de RETURNS données peut être n'importe quel type de données Amazon Redshift standard. Pour de plus amples informations, veuillez consulter Types UDF de données Python.

VOLATILE | STABLE

Informe l’optimiseur de requête à propos de l’instabilité de la fonction.

Pour obtenir la meilleure optimisation possible, qualifiez votre fonction avec la catégorie d’instabilité la plus stricte qui s’y applique. En matière de rigueur, en commençant par la moins stricte, les catégories d’instabilité sont les suivantes :

  • VOLATILE

  • STABLE

VOLATILE

Soit les mêmes arguments, la fonction peut renvoyer des résultats différents sur des appels successifs, y compris pour les lignes d’une même instruction. L’optimiseur de requête ne peut pas émettre d’hypothèses concernant le comportement d’une fonction volatile. Une requête qui utilise une fonction volatile doit réévaluer la fonction pour chaque entrée.

STABLE

À partir des mêmes arguments, la fonction renvoie invariablement les mêmes résultats lors des appels successifs traités au sein d’une même instruction. La fonction peut renvoyer des résultats différents lorsqu’elle est appelée dans différents instructions. Cette catégorie vise ici à permettre à l’optimiseur de réduire le nombre de fois que la fonction est appelée au sein d’une même instruction.

Notez que si la rigueur choisie n’est pas valide pour la fonction, l’optimiseur risque d’ignorer certains appels basés sur cette rigueur. Cela peut produire un jeu de résultats incorrect.

La IMMUTABLE clause n'est actuellement pas prise en charge pour LambdaUDFs.

LAMBDA'lambda_fn_name'

Nom de la fonction qu’Amazon Redshift appelle.

Pour connaître les étapes de création d'une AWS Lambda fonction, voir Créer une fonction Lambda avec la console dans le Guide du AWS Lambda développeur.

Pour obtenir des informations sur les autorisations requises pour la fonction Lambda, consultez Autorisations AWS Lambda dans le Guide du développeur AWS Lambda .

IAM_ ROLE {par défaut | 'arn:aws:iam : :<Compte AWS-id>:rôle/<role-name>

Utilisez le mot clé par défaut pour qu'Amazon Redshift utilise le IAM rôle défini par défaut et associé au cluster lors de l'exécution de la CREATE EXTERNAL FUNCTION commande.

Utilisez le nom de ressource Amazon (ARN) pour un IAM rôle utilisé par votre cluster pour l'authentification et l'autorisation. La CREATE EXTERNAL FUNCTION commande est autorisée à invoquer des fonctions Lambda via ce IAM rôle. Si votre cluster possède un IAM rôle existant auquel sont associées des autorisations permettant d'invoquer des fonctions Lambda, vous pouvez remplacer celui de votre rôle. ARN Pour de plus amples informations, veuillez consulter Configuration du paramètre d'autorisation pour Lambda UDFs.

Voici la syntaxe du ROLE paramètre IAM _.

IAM_ROLE 'arn:aws:iam::aws-account-id:role/role-name'
RETRY_ TIMEOUT millisecondes

Durée totale en millisecondes utilisée par Amazon Redshift pour les retards dans les interruptions de nouvelles tentatives.

Au lieu de lancer de nouvelles tentatives immédiatement pour toute requête ayant échoué, Amazon Redshift effectue des interruptions et attend un certain temps entre les nouvelles tentatives. Amazon Redshift tente ensuite de relancer la requête ayant échoué jusqu'à ce que la somme de tous les délais soit égale ou supérieure à la TIMEOUT valeur RETRY _ que vous avez spécifiée. La valeur par défaut est de 20 000 millisecondes.

Lorsqu’une fonction Lambda est appelée, Amazon Redshift lance une nouvelle tentative pour les requêtes qui reçoivent des erreurs telles que TooManyRequestsException, EC2ThrottledException et ServiceException.

Vous pouvez définir le TIMEOUT paramètre RETRY _ à 0 milliseconde pour empêcher toute nouvelle tentative pour un Lambda. UDF

MAX_ BATCH _ ROWS compter

Nombre maximum de lignes qu’Amazon Redshift envoie dans une seule demande par lot pour une seule invocation Lambda.

La valeur minimale pour ce paramètre est 1. La valeur maximale est INT _MAX, soit 2 147 483 647.

Ce paramètre est facultatif. La valeur par défaut est INT _MAX, ou 2 147 483 647.

MAX_ BATCH _ SIZE taille [KB | MB]

Taille maximum de la charge utile de données qu’Amazon Redshift envoie dans une seule demande par lot pour une seule invocation Lambda.

La valeur minimale pour ce paramètre est 1 Ko. La valeur maximale est 5 Mo.

La valeur par défaut de ce paramètre est 5 Mo.

Ko et Mo sont facultatifs. Si vous ne définissez pas l’unité de mesure, Amazon Redshift utilise Ko par défaut.

Notes d’utilisation

Tenez compte des points suivants lorsque vous créez Lambda UDFs :

  • L’ordre des appels de fonctions Lambda au niveau des arguments d’entrée n’est ni fixe ni garanti. Il peut varier selon les instances de requêtes en cours d’exécution, en fonction de la configuration du cluster.

  • Il n’est pas garanti que les fonctions soient appliquées une seule fois à chaque argument d’entrée. L'interaction entre Amazon Redshift et Amazon Redshift AWS Lambda peut entraîner des appels répétitifs avec les mêmes entrées.

Exemples

Vous trouverez ci-dessous des exemples d'utilisation de fonctions scalaires Lambda définies par l'utilisateur (). UDFs

Exemple de UDF Lambda scalaire utilisant une fonction Lambda Node.js

L’exemple suivant crée une fonction externe appelée exfunc_sum qui prend deux entiers comme arguments d’entrée. Cette fonction renvoie la somme sous la forme d’une sortie de nombre entier. Le nom de la fonction Lambda à appeler est lambda_sum. Le langage utilisé pour cette fonction Lambda est Node.js 12.x. Assurez-vous de spécifier le IAM rôle. L'exemple utilise 'arn:aws:iam::123456789012:user/johndoe' comme IAM rôle.

CREATE EXTERNAL FUNCTION exfunc_sum(INT,INT) RETURNS INT VOLATILE LAMBDA 'lambda_sum' IAM_ROLE 'arn:aws:iam::123456789012:role/Redshift-Exfunc-Test';

La fonction Lambda prend la charge utile de la requête et effectue une itération sur chaque ligne. Toutes les valeurs d’une seule ligne sont ajoutées pour calculer la somme de cette ligne, qui est enregistrée dans la table de réponses. Le nombre de lignes dans la table de résultats est similaire au nombre de lignes reçues dans la charge utile de la requête.

La charge utile de JSON réponse doit contenir les données de résultat dans le champ « résultats » pour qu'elle soit reconnue par la fonction externe. Le champ arguments de la requête envoyée à la fonction Lambda contient la charge utile de données. Il peut y avoir plusieurs lignes dans la charge utile de données en cas de requête par lots. La fonction Lambda suivante effectue une itération sur toutes les lignes de la charge utile de données de la requête. Elle effectue également une itération individuelle sur toutes les valeurs d’une seule ligne.

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

L’exemple suivant appelle la fonction externe avec des valeurs littérales.

select exfunc_sum(1,2); exfunc_sum ------------ 3 (1 row)

L’exemple suivant crée une table appelée t_sum avec deux colonnes, c1 et c2, du type de données entier et insère deux lignes de données. Ensuite, la fonction externe est appelée en transmettant les noms de colonne de cette table. Les deux lignes de la table sont envoyées dans une requête par lots dans la charge utile de la requête sous la forme d’une seule invocation 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)

Exemple de UDF Lambda scalaire utilisant l'attribut _ RETRY TIMEOUT

Dans la section suivante, vous trouverez un exemple d'utilisation de l'TIMEOUTattribut RETRY _ dans LambdaUDFs.

AWS Lambda les fonctions ont des limites de simultanéité que vous pouvez définir pour chaque fonction. Pour plus d'informations sur les limites de simultanéité, consultez la section Gestion de la simultanéité pour une fonction Lambda dans le Guide du AWS Lambda développeur et l'article Gestion de la simultanéité des AWS Lambda fonctions sur le blog Compute. AWS

Lorsque le nombre de demandes traitées par un Lambda UDF dépasse les limites de simultanéité, les nouvelles demandes reçoivent l'erreur. TooManyRequestsException Le Lambda UDF essaie de corriger cette erreur jusqu'à ce que la somme de tous les délais entre les demandes envoyées à la fonction Lambda soit égale ou supérieure à la valeur RETRY _ TIMEOUT que vous avez définie. La TIMEOUT valeur RETRY _ par défaut est de 20 000 millisecondes.

L’exemple suivant utilise une fonction Lambda nommée exfunc_sleep_3. Cette fonction prend la charge utile de la requête, effectue une itération sur chaque ligne et convertit l’entrée en majuscules. Ensuite, elle passe en veille pendant 3 secondes puis renvoie le résultat. Le langage utilisé pour cette fonction Lambda est Python 3.8.

Le nombre de lignes dans la table de résultats est similaire au nombre de lignes reçues dans la charge utile de la requête. La charge utile de JSON réponse doit contenir les données de résultat results sur le terrain pour qu'elle soit reconnue par la fonction externe. Le champ arguments dans la requête envoyée à la fonction Lambda contient la charge utile de données. Dans le cas d’une requête par lots, plusieurs lignes peuvent apparaître dans la charge utile de données.

La limite de simultanéité pour cette fonction est spécifiquement fixée à 1 en cas de simultanéité réservée afin de démontrer l'utilisation de l'attribut RETRY _TIMEOUT. Lorsque l’attribut est défini sur 1, la fonction Lambda ne peut servir qu’une seule requête à la fois.

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

Voici deux exemples supplémentaires illustrant l'TIMEOUTattribut RETRY _. Ils invoquent chacun un seul LambdaUDF. Lors de l'appel du UDF Lambda, chaque exemple exécute la SQL même requête pour appeler le UDF Lambda à partir de deux sessions de base de données simultanées en même temps. Lorsque la première requête qui invoque le UDF Lambda est traitée par le, UDF la deuxième requête reçoit TooManyRequestsException l'erreur. Ce résultat est dû au fait que vous avez spécifiquement défini la simultanéité réservée dans le UDF to 1. Pour obtenir des informations sur la définition de la simultanéité réservée pour les fonctions Lambda, consultez Configuration de la simultanéité réservée.

Le premier exemple ci-dessous définit l'TIMEOUTattribut RETRY _ pour le Lambda UDF à 0 milliseconde. Si la requête Lambda reçoit des exceptions de la fonction Lambda, Amazon Redshift n’effectue pas de nouvelle tentative. Ce résultat est dû au fait que TIMEOUT l'attribut RETRY _ est défini sur 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;

Lorsque le RETRY _ est TIMEOUT défini sur 0, vous pouvez exécuter les deux requêtes suivantes à partir de sessions de base de données distinctes pour obtenir des résultats différents.

La première SQL requête utilisant le Lambda UDF s'exécute correctement.

select exfunc_upper('Varchar'); exfunc_upper -------------- VARCHAR (1 row)

La deuxième requête, qui est exécutée à partir d’une séance de base de données distincte en même temps, renvoie l’erreur 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] -----------------------------------------------

Le deuxième exemple, ci-dessous, définit l'TIMEOUTattribut RETRY _ pour le Lambda UDF à 3 000 millisecondes. Même si la deuxième requête est exécutée simultanément, le UDF Lambda réessaie jusqu'à ce que le délai total soit de 3 000 millisecondes. Ainsi, les deux requêtes s’exécutent avec succès.

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;

Avec le RETRY _ TIMEOUT défini sur 3 000 millisecondes, vous pouvez exécuter les deux requêtes suivantes à partir de sessions de base de données distinctes pour obtenir les mêmes résultats.

La première SQL requête qui exécute le Lambda UDF s'exécute correctement.

select exfunc_upper('Varchar'); exfunc_upper -------------- VARCHAR (1 row)

La deuxième requête s'exécute simultanément et le UDF Lambda réessaie jusqu'à ce que le délai total soit de 3 000 millisecondes.

select exfunc_upper('Varchar'); exfunc_upper -------------- VARCHAR (1 row)

Exemple de UDF Lambda scalaire utilisant une fonction Lambda en Python

L’exemple suivant crée une fonction externe appelée exfunc_multiplication qui multiplie les nombres et renvoie un nombre entier. Cet exemple intègre les champs success et error_msg dans la réponse Lambda. Le champ success est défini sur false lorsqu’il y a un dépassement d’entier dans le résultat de la multiplication et que la valeur du message error_msg est définie sur Integer multiplication overflow. La fonction exfunc_multiplication prend trois nombres entiers comme arguments d’entrée et renvoie la somme sous la forme d’une sortie de nombre entier.

Le nom de la fonction Lambda qui est appelée est lambda_multiplication. Le langage utilisé pour cette fonction Lambda est Python 3.8. Assurez-vous de spécifier le IAM rôle.

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 fonction Lambda prend la charge utile de la requête et effectue une itération sur chaque ligne. Toutes les valeurs d’une seule ligne sont multipliées pour calculer le résultat de cette ligne, qui est enregistré dans la liste de réponses. Cet exemple utilise une valeur success booléenne définie sur true par défaut. Si le résultat de multiplication d’une ligne a un dépassement d’entier, la valeur success est définie sur false. Ensuite, la boucle d’itération s’arrête.

Lorsque la charge utile de la réponse est créée, si la valeur success est false, la fonction Lambda suivante ajoute le champ error_msg dans la charge utile. Elle définit également le message d’erreur sur Integer multiplication overflow. Si la valeur success est true, les données de résultat sont ajoutées dans le champ results. Le nombre de lignes dans la table de résultats, le cas échéant, est similaire au nombre de lignes reçues dans la charge utile de la requête.

Le champ arguments de la requête envoyée à la fonction Lambda contient la charge utile de données. Il peut y avoir plusieurs lignes dans la charge utile de données en cas de demande par lots. La fonction Lambda suivante effectue une itération sur toutes les lignes de la charge utile de données de la requête et effectue une itération individuelle sur toutes les valeurs au sein d’une seule ligne.

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

L’exemple suivant appelle la fonction externe avec des valeurs littérales.

SELECT exfunc_multiplication(8, 9, 2); exfunc_multiplication --------------------------- 144 (1 row)

L’exemple suivant crée une table nommée t_multi avec trois colonnes, c1, c2 et c3, du type de données entier. La fonction externe est appelée en transmettant les noms de colonnes de cette table. Les données sont insérées de manière à provoquer un dépassement d’entier afin de montrer comment l’erreur est propagée.

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