CREATE EXTERNAL FUNCTION - Amazon Redshift

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

CREATE EXTERNAL FUNCTION

Erstellt eine skalare benutzerdefinierte Funktion (UDF), die auf AWS Lambda Amazon Redshift basiert. Weitere Informationen zu benutzerdefinierten Lambda-Funktionen finden Sie unter Erstellen einer skalaren Lambda-UDF.

Erforderliche Berechtigungen

Für CREATE EXTERNAL FUNCTION sind folgende Berechtigungen erforderlich:

  • Superuser

  • Benutzer mit der Berechtigung CREATE [OR REPLACE] EXTERNAL FUNCTION

Syntax

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

Parameter

OR REPLACE

Die Klausel gibt an, dass die vorhandene Funktion ersetzt wird, wenn eine Funktion mit demselben Namen und denselben Eingabeargument-Datentypen bzw. derselben Signatur vorhanden ist. Sie können eine Funktion nur durch eine neue Funktion ersetzen, wenn diese einen identischen Satz von Datentypen definiert. Sie müssen Superuser sein, um eine Funktion zu ersetzen.

Wenn Sie eine Funktion definieren, die den gleichen Namen wie eine vorhandene Funktion, aber eine andere Signatur besitzt, erstellen Sie eine neue Funktion. Der Funktionsname wird also überladen. Weitere Informationen finden Sie unter Überladen von Funktionsnamen.

external_fn_name

Der Name der externen Funktion. Wenn Sie einen Schemanamen angeben (z. B. myschema.myfunction), wird die Funktion unter Verwendung des angegebenen Schemas erstellt. Andernfalls wird die Funktion im aktuellen Schema erstellt. Weitere Informationen zu gültigen Namen finden Sie unter Namen und Kennungen.

Es wird empfohlen, dass Sie alle UDFs mit dem Präfix benennen f_. Amazon Redshift reserviert das Präfix f_ für UDF-Namen. Durch die Verwendung des f_-Präfixes stellen Sie sicher, dass Ihr UDF-Name nicht mit den SQL-Funktionsnamen für Amazon Redshift kollidiert, weder jetzt noch in Zukunft. Weitere Informationen finden Sie unter Benennung von UDFs.

data_type

Der Datentyp der Eingabeargumente. Weitere Informationen finden Sie unter Datentypen.

RETURNS data_type

Der Datentyp des Werts, der von der Funktion zurückgegeben wird. Der RETURNS-Datentyp kann ein beliebiger Standard-Amazon-Redshift-Datentyp sein. Weitere Informationen finden Sie unter Python-UDF-Datentypen.

VOLATILE | STABLE

Informiert den Abfragenoptimierer über die Volatilität der Funktion.

Um die beste Optimierung zu erzielen, kennzeichnen Sie Ihre Funktion mit der strengsten Volatilitätskategorie, die für sie gültig ist. Beginnend mit der Volatilitätskategorie mit der geringsten Strenge sind dies die Volatilitätskategorien:

  • VOLATILE

  • STABLE

VOLATILE

Bei gleichen Argumenten kann die Funktion unterschiedliche Ergebnisse für aufeinanderfolgende Aufrufe zurückgeben, auch für die Zeilen in einer einzelnen Anweisung. Der Abfrageoptimierer kann keine Annahmen über das Verhalten einer volatilen Funktion treffen. Eine Abfrage, die eine volatile Funktion verwendet, muss die Funktion für jede Eingabe neu auswerten.

STABLE

Bei gleichen Argumenten gibt die Funktion garantiert die gleichen Ergebnisse für alle aufeinderfolgenden Aufrufe zurück, die innerhalb einer einzelnen Anweisung verarbeitet werden. Die Funktion kann unterschiedliche Ergebnisse zurückgeben, wenn sie in unterschiedlichen Anweisungen aufgerufen wird. Diese Kategorie ermöglicht es dem Optimierer, die Häufigkeit zu reduzieren, mit der die Funktion innerhalb einer einzigen Anweisung aufgerufen wird.

Beachten Sie, dass, wenn die ausgewählte Strenge für die Funktion nicht gültig ist, das Risiko besteht, dass der Optimierer aufgrund dieser Strenge einige Aufrufe überspringt. Dies kann zu einer falschen Ergebnismenge führen.

Die Klausel IMMUTABLE wird derzeit für Lambda-UDFs nicht unterstützt.

LAMBDA 'lambda_fn_name'

Der Name der Funktion, die Amazon Redshift aufruft.

Schritte zum Erstellen einer AWS Lambda Funktion finden Sie unter Erstellen einer Lambda-Funktion mit der Konsole im AWS Lambda Entwicklerhandbuch.

Informationen zu den für die Lambda-Funktion erforderlichen Berechtigungen finden Sie unter AWS Lambda -Berechtigungen im AWS Lambda -Entwicklerhandbuch.

IAM_ROLE { default | ‘arn:aws:iam::<AWS-Konto-id>:role/<role-name>

Verwenden Sie das Standardstichwort, damit Amazon Redshift die IAM-Rolle verwendet, die als Standard festgelegt und mit dem Cluster verknüpft ist, wenn der CREATE EXTERNAL FUNCTION-Befehl ausgeführt wird.

Verwenden Sie den Amazon-Ressourcennamen (ARN) für eine IAM-Rolle, die von Ihrem Cluster für Authentifizierung und Autorisierung verwendet wird. Der Befehl CREATE EXTERNAL FUNCTION ist berechtigt, über diese IAM-Rolle Lambda-Funktionen aufzurufen. Wenn Ihr Cluster über eine bestehende IAM-Rolle mit Berechtigungen zum Aufrufen von Lambda-Funktionen verfügt, können Sie den ARN Ihrer Rolle ersetzen. Weitere Informationen finden Sie unter Konfigurieren des Autorisierungsparameters für Lambda-UDFs.

Im Folgenden wird die Syntax für den Parameter IAM_ROLE gezeigt.

IAM_ROLE 'arn:aws:iam::aws-account-id:role/role-name'
RETRY_TIMEOUT Millisekunden

Die Gesamtzeit in Millisekunden, die Amazon Redshift für die Verzögerungen bei Wiederholungs-Backoffs verwendet.

Anstatt es bei fehlgeschlagenen Abfragen sofort erneut zu versuchen, führt Amazon Redshift Backoffs durch und wartet eine bestimmte Zeit zwischen den Wiederholungsversuchen. Dann wiederholt Amazon Redshift die Anfrage, um die fehlgeschlagene Abfrage erneut auszuführen, bis die Summe aller Verzögerungen gleich oder größer als der von Ihnen angegebene RETRY_TIMEOUT-Wert ist. Der Standardwert ist 20 000 Millisekunden.

Wenn eine Lambda-Funktion aufgerufen wird, wiederholt Amazon Redshift Abfragen, bei denen Fehler wie TooManyRequestsException, EC2ThrottledException und ServiceException auftreten.

Sie können den Parameter RETRY_TIMEOUT auf 0 Millisekunden setzen, um Wiederholungsversuche für eine Lambda-UDF zu verhindern.

MAX_BATCH_ROWS Anzahl

Die maximale Zeilenanzahl, die Amazon Redshift in einer einzelnen Batch-Anforderung für einen einzelnen Lambda-Aufruf sendet.

Der Mindestwert für diesen Parameter ist 1. Der maximale Wert lautet INT_MAX oder 2 147 483 647.

Dieser Parameter ist optional. Der Standardwert lautet INT_MAX oder 2 147 483 647.

MAX_BATCH_SIZE Größe [ KB | MB ]

Die maximale Größe der Datennutzlast, die Amazon Redshift in einer einzelnen Batch-Anforderung für einen einzelnen Lambda-Aufruf sendet.

Der Mindestwert für diesen Parameter ist 1 KB. Der maximale Wert ist 5 MB.

Der Standardwert für diesen Parameter ist 5 MB.

KB und MB sind optional. Wenn Sie die Maßeinheit nicht festlegen, verwendet Amazon Redshift standardmäßig KB.

Nutzungshinweise

Beachten Sie beim Erstellen von Lambda-UDFs Folgendes:

  • Die Reihenfolge der Lambda-Funktionsaufrufe für die Eingabeargumente ist nicht festgelegt oder garantiert. Dies kann je nach Cluster-Konfiguration von Instance zu Instance variieren, für die Abfragen ausgeführt werden.

  • Es wird nicht garantiert, dass die Funktionen tatsächlich nur einmal auf jedes Eingabeargument angewendet werden. Die Interaktion zwischen Amazon Redshift und AWS Lambda kann zu wiederholten Aufrufen mit denselben Eingaben führen.

Beispiele

Nachfolgend finden Sie Beispiele für die Verwendung skalarer benutzerdefinierter Lambda-Funktionen (UDFs).

Skalares Lambda-UDF-Beispiel mit einer Node.js-Lambda-Funktion

Im folgenden Beispiel wird eine externe Funktion namens exfunc_sum erstellt, die zwei Ganzzahlen als Eingabeargumente benötigt. Diese Funktion gibt die Summe als Ganzzahl aus. Der Name der aufzurufenden Lambda-Funktion lautet lambda_sum. Die für diese Lambda-Funktion verwendete Sprache ist Node.js 12.x. Stellen Sie sicher, dass Sie die IAM-Rolle angeben. Das Beispiel verwendet 'arn:aws:iam::123456789012:user/johndoe' als IAM-Rolle.

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

Die Lambda-Funktion verarbeitet die Nutzlast der Anfrage und iteriert über jede Zeile. Alle Werte in einer einzelnen Zeile werden addiert, um die Summe für diese Zeile zu berechnen, die im Antwort-Array gespeichert wird. Die Anzahl der Zeilen im Ergebnis-Array entspricht der Anzahl der in der Nutzlast der Anfrage empfangenen Zeilen.

Die JSON-Antwort-Nutzlast muss die Ergebnisdaten im Feld „results“ enthalten, damit sie von der externen Funktion erkannt werden kann. Das Feld „arguments“ in der Anforderung, die an die Lambda Funktion gesendet wird, enthält die Datennutzlast. Bei einer Batch-Anforderung können mehrere Zeilen in den Nutzdaten vorhanden sein. Die folgende Lambda-Funktion iteriert über alle Zeilen in der Nutzlast der Anfragedaten. Sie durchläuft zudem alle Werte innerhalb einer einzelnen Zeile.

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

Im folgenden Beispiel wird die externe Funktion mit Literalwerten aufgerufen.

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

Im folgenden Beispiel wird eine Tabelle namens t_sum mit zwei Spalten, c1 und c2, vom Datentyp Ganzzahl erstellt und zwei Datenzeilen werden eingefügt. Dann wird die externe Funktion aufgerufen, indem die Spaltennamen dieser Tabelle übergeben werden. Die beiden Tabellenzeilen werden in einer Batch-Anforderung in der Anforderungsnutzlast als einzelner Lambda-Aufruf gesendet.

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)

Skalares Lambda-UDF-Beispiel unter Verwendung des RETRY_TIMEOUT-Attributs

Im folgenden Abschnitt finden Sie ein Beispiel für die Verwendung des Attributs RETRY_TIMEOUT in Lambda-UDFs.

AWS Lambda Für Funktionen gibt es Grenzwerte für die Parallelität, die Sie für jede Funktion festlegen können. Weitere Informationen zu Parallelitätslimits finden Sie unter Managing Concurrency for a Lambda function im AWS Lambda Developer Guide und im Beitrag Managing AWS Lambda Function Concurrency im Compute-Blog. AWS

Wenn die Anzahl der Anfragen, die von einer Lambda-UDF bedient werden, die Nebenläufigkeitslimits überschreitet, wird bei neuen Anfragen der Fehler TooManyRequestsException ausgegeben. Die Lambda-UDF versucht es bei diesem Fehler so lange erneut, bis die Summe aller Verzögerungen zwischen den an die Lambda-Funktion gesendeten Anforderungen dem von Ihnen festgelegten Wert RETRY_TIMEOUT entspricht oder diesen überschreitet. Der Standardwert für RETRY_TIMEOUT ist 20 000 Millisekunden.

Im folgenden Beispiel wird die Lambda-Funktion mit dem Namen erstellt exfunc_sleep_3. Diese Funktion verarbeitet die Nutzdaten der Anfrage, iteriert über jede Zeile und konvertiert die Eingabe in Großbuchstaben. Dann wartet sie 3 Sekunden und gibt das Ergebnis zurück. Die für diese Lambda-Funktion verwendete Sprache ist Python 3.8.

Die Anzahl der Zeilen im Ergebnis-Array entspricht der Anzahl der in der Nutzlast der Anfrage empfangenen Zeilen. Die JSON-Antwort-Nutzlast muss die Ergebnisdaten im Feld results enthalten, damit sie von der externen Funktion erkannt werden kann. Das Feld arguments in der Anforderung, die an die Lambda Funktion gesendet wird, enthält die Datennutzlast. Bei einer Batch-Anforderung können mehrere Zeilen in den Nutzdaten enthalten sein.

Das Nebenläufigkeitslimit für diese Funktion ist speziell auf 1 für die reservierte Nebenläufigkeit festgelegt, um die Verwendung des Attributs RETRY_TIMEOUT zu demonstrieren. Wenn das Attribut auf 1 gesetzt ist, kann die Lambda-Funktion jeweils nur eine Anfrage bedienen.

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

Im Folgenden werden zwei weitere Beispiele für das RETRY_TIMEOUT-Attribut beschrieben. Sie rufen jeweils eine einzelne Lambda-UDF auf. Beim Aufrufen der Lambda-UDF wird in jedem Beispiel dieselbe SQL-Abfrage ausgeführt, um die Lambda-UDF von zwei nebenläufigen Datenbanksitzungen aus aufzurufen. Wenn die erste Abfrage, die die Lambda-UDF aufruft, von der UDF bedient wird, wird für die zweite Abfrage der Fehler TooManyRequestsException angezeigt. Dieses Ergebnis tritt auf, weil Sie die reservierte Nebenläufigkeit in der UDF speziell auf 1 gesetzt haben. Informationen zum Festlegen der reservierten Nebenläufigkeit für Lambda-Funktionen finden Sie unter Konfigurieren reservierter Gleichzeitigkeit.

Im folgenden ersten Beispiel wird das RETRY_TIMEOUT-Attribut für die Lambda-UDF auf 0 Millisekunden gesetzt. Wenn die Lambda-Anforderung eine Ausnahme von der Lambda-Funktion erhält, führt Amazon Redshift keine Wiederholungsversuche durch. Dieses Ergebnis tritt auf, weil das Attribut RETRY_TIMEOUT auf 0 gesetzt ist.

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;

Wenn RETRY_TIMEOUT auf 0 gesetzt ist, können Sie die folgenden zwei Abfragen in verschiedenen Datenbanksitzungen ausführen, um unterschiedliche Ergebnisse zu erhalten.

Die erste SQL-Abfrage, die die Lambda-UDF verwendet, wird erfolgreich ausgeführt.

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

Für die zweite Abfrage, die in einer separaten Datenbanksitzung zur gleichen Zeit ausgeführt wird, wird der Fehler TooManyRequestsException angezeigt.

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

Im folgenden zweiten Beispiel wird das RETRY_TIMEOUT-Attribut für die Lambda-UDF auf 3 000 Millisekunden gesetzt. Selbst wenn die zweite Abfrage gleichzeitig ausgeführt wird, wiederholt die Lambda-UDF den Vorgang, bis die Gesamtverzögerung 3 000 Millisekunden beträgt. Daher werden beide Abfragen erfolgreich ausgeführt.

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;

Wenn RETRY_TIMEOUT auf 3 000 Millisekunden eingestellt ist, können Sie die folgenden beiden Abfragen in verschiedenen Datenbanksitzungen ausführen, um dieselben Ergebnisse zu erhalten.

Die erste SQL-Abfrage, die die Lambda-UDF verwendet, wird erfolgreich ausgeführt.

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

Die zweite Abfrage wird gleichzeitig ausgeführt, und die Lambda-UDF versucht es erneut, bis die Gesamtverzögerung 3 000 Millisekunden beträgt.

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

Skalares Lambda-UDF-Beispiel mit einer Python-Lambda-Funktion

Im folgenden Beispiel wird eine externe Funktion namens exfunc_multiplication erstellt, die Zahlen multipliziert und eine Ganzzahl zurückgibt. In diesem Beispiel sind die Erfolgs- und error_msg-Felder in der Lambda-Antwort enthalten. Das Erfolgsfeld wird auf false gesetzt, wenn ein Ganzzahlüberlauf im Multiplikationsergebnis vorliegt, und die Meldung error_msg wird auf Integer multiplication overflow gesetzt. Die exfunc_multiplication-Funktion nimmt drei Ganzzahlen als Eingabeargumente und gibt die Summe als Ganzzahl aus.

Der Name der Lambda-Funktion, die aufgerufen wird, lautet lambda_multiplication. Die für diese Lambda-Funktion verwendete Sprache ist Python 3.8. Stellen Sie sicher, dass Sie die IAM-Rolle angeben.

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

Die Lambda-Funktion verarbeitet die Nutzlast der Anfrage und iteriert über jede Zeile. Die Werte in einer einzelnen Zeile werden multipliziert, um das Ergebnis für diese Zeile zu berechnen, das dann in der Antwortliste gespeichert wird. In diesem Beispiel wird ein boolescher Erfolgswert verwendet, der standardmäßig auf true gesetzt ist. Wenn das Multiplikationsergebnis für eine Zeile einen Ganzzahlüberlauf aufweist, wird der Erfolgswert auf false gesetzt. Dann bricht die Iterationsschleife ab.

Wenn der Erfolgswert beim Erstellen der Antwort-Nutzdaten falsch ist, fügt die folgende Lambda-Funktion das Feld error_msg in die Nutzdaten ein. Es setzt auch die Fehlermeldung auf Integer multiplication overflow. Wenn der Erfolgswert true ist, werden die Ergebnisdaten in das Ergebnisfeld eingefügt. Die Anzahl der Zeilen im Ergebnis-Array, sofern vorhanden, entspricht der Anzahl der in der Nutzlast der Anfrage empfangenen Zeilen.

Das Feld „arguments“ in der Anforderung, die an die Lambda Funktion gesendet wird, enthält die Datennutzlast. Bei einer Batch-Anforderung können mehrere Zeilen in den Nutzdaten vorhanden sein. Die folgende Lambda-Funktion iteriert über alle Zeilen in der Nutzlast der Anfragedaten und iteriert einzeln über alle Werte innerhalb einer einzelnen Zeile.

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

Im folgenden Beispiel wird die externe Funktion mit Literalwerten aufgerufen.

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

Im folgenden Beispiel wird eine Tabelle mit dem Namen t_multi mit drei Spalten, c1, c2 und c3, vom Datentyp Ganzzahl erstellt. Dann wird die externe Funktion aufgerufen, indem die Spaltennamen dieser Tabelle übergeben werden. Die Daten werden so eingefügt, dass sie einen Ganzzahlüberlauf verursachen, um zu zeigen, wie der Fehler verteilt ist.

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