Plattformunabhängige Informationen zum Erstellen externer Funktionen

Ein Großteil der Informationen zur Entwicklung eines Proxydienstes und eines Remotedienstes sind plattformabhängig. Es gibt jedoch viele zusätzliche Details, die plattformunabhängig sind.

Unter diesem Thema werden diese plattformunabhängigen Details beschrieben.

Unter diesem Thema:

Remotedienst

Dateiformat

Snowflake ruft eine Ressource in einem Proxydienst auf, indem eine HTTP-POST-Anforderung ausgeführt wird. Diese POST-Anforderung enthält Daten in einem bestimmten Format sowie bestimmte Header. Die als Ergebnis von POST zurückgegebenen Daten müssen ebenfalls einem bestimmten Format entsprechen. Beide Formate werden unten beschrieben.

Von Snowflake gesendetes Datenformat

Jede HTTP-Anforderung von Snowflake ist eine POST-Anforderung. Die POST-Anforderung enthält Header und einen Body. Metadaten werden in HTTP-Headern übergeben. Die Daten werden als Batch zusammengefasst und im Body der POST-Anforderung übergeben.

Zu diesen Informationen gehören:

  • Metadaten, die in den Eigenschaften „headers“ und „context_headers“ von CREATE EXTERNAL FUNCTION beschrieben sind.

  • Es gibt folgende HTTP-Header:

    • Header, die beschreiben, wie Daten im Body der Anforderung serialisiert sind:

      • „sf-external-function-format“: Dies ist derzeit immer auf „json“ eingestellt.

      • „sf-external-function-format-version“: Dies ist derzeit immer auf „1.0“ eingestellt.

    • „sf-external-function-current-query-id“: Enthält die Abfrage-ID der Abfrage, die diese externe Funktion aufgerufen hat. Sie können diese verwenden, um Snowflake-Abfragen mit Aufrufen des Remotedienstes zu korrelieren, um beispielsweise Probleme zu beheben.

Der Body der POST-Anforderung enthält die Daten, die im JSON-Format serialisiert sind. Das Schema für JSON lautet:

  • Das JSON-Objekt der obersten Ebene ist ein Wörterbuch mit Name/Wert-Paaren.

  • Derzeit gibt es genau einen Eintrag im Wörterbuch. Der Schlüssel für dieses Element heißt „data“.

  • Der Wert dieses „data“-Elements ist ein JSON-Array, in dem jedes Array-Element eine Datenzeile ist.

  • Jede Datenzeile ist ein JSON-Array aus einer oder mehreren Spalten.

  • Die erste Spalte ist immer die Zeilennummer (d. h. der 0-basierte Index der Zeile innerhalb des Batches).

  • Die verbleibenden Spalten enthalten die Argumente für die Funktion.

  • Datentypen werden wie folgt serialisiert:

    • Nummern werden als JSON-Nummern serialisiert.

    • Boolesche Werte werden als Boolesche JSON-Werte serialisiert.

    • Zeichenfolgen werden als JSON-Zeichenfolgen serialisiert.

    • Variant-Werte werden als JSON-Objekte serialisiert.

    • Alle anderen unterstützten Datentypen werden als JSON-Zeichenfolgen serialisiert.

    • NULL wird als JSON-Null serialisiert.

Hier ist ein Beispiel für eine serialisierte Anforderung für einen Remotedienst mit der Signatur f(integer, integer, varchar, timestamp):

{
    "data": [
                [0, 10, "Alex", "Wed, 01 Jan 2014 16:00:00 -0800"],
                [1, 20, "Steve", "Wed, 01 Jan 2015 16:00:00 -0800"],
                [2, 30, "Alice", "Wed, 01 Jan 2016 16:00:00 -0800"],
                [3, 40, "Adrian", "Wed, 01 Jan 2017 16:00:00 -0800"]
            ]
}

Optional können JSON-Daten für die Übertragung über das Netzwerk komprimiert werden. Die Komprimierung ist in CREATE EXTERNAL FUNCTION dokumentiert.

Snowflake sendet diese Daten an den Proxydienst und nicht direkt an den Remotedienst. Daher muss der Proxydienst Daten in einem Snowflake-kompatiblen Format empfangen (und zurückgeben). Obwohl der Proxydienst normalerweise Daten unverändert weiterleitet, kann der Proxy zu sendende und zu empfangende Daten neu formatieren, um die Anforderungen sowohl des Remotedienstes als auch von Snowflake zu erfüllen.

Der Einfachheit halber und zur Veranschaulichung der Formate, die Snowflake voraussichtlich senden und empfangen wird, wird in den meisten Beispielen in diesem Abschnitt davon ausgegangen, dass der Remotedienst Daten im gleichen Format liest und schreibt, das Snowflake erwartet, und dass der Proxydienst Daten unverändert in beide Richtungen weiterleitet.

Von Snowflake empfangenes Datenformat

Das Format der von Snowflake empfangenen Daten ähnelt dem Format der von Snowflake gesendeten Daten. Der zurückgegebene Wert liegt im JSON-Format vor.

{
    "data":
        [
            [ 0, 1995 ],
            [ 1, 1974 ],
            [ 2, 1983 ],
            [ 3, 2001 ]
        ]
}

Die an Snowflake zurückgegebene JSON-Antwort sollte eine Zeile für jede von Snowflake gesendete Zeile enthalten. Jede zurückgegebene Zeile enthält zwei Werte:

  • Die Zeilennummer (d. h. der 0-basierte Index der Zeile innerhalb des Batches).

  • Der von der Funktion für diese Zeile zurückgegebene Wert. Der Wert kann ein zusammengesetzter Wert sein (z. B. ein VARIANT), muss jedoch genau ein Wert sein, da alle skalaren Snowflake-Funktionen (extern oder anderweitig) einen einzelnen Wert zurückgeben.

Die Zeilennummern in den zurückgegebenen Daten müssen den Zeilennummern in den von Snowflake gesendeten Daten entsprechen und in derselben Reihenfolge zurückgegeben werden, in der sie empfangen wurden.

Diese JSON-Daten bilden den Body der HTTP-Antwort. Die Antwort enthält auch HTTP-Header und einen Statuscode (z. B. zeigt Statuscode 200 Erfolg an).

Optional können JSON-Daten für die Übertragung über das Netzwerk komprimiert werden. Die Komprimierung ist in CREATE EXTERNAL FUNCTION dokumentiert.

Snowflake erkennt die folgenden HTTP-Statuscodes:

Code

Beschreibung

200

Kein Fehler

Andere Werte werden als Fehler behandelt.

Diese Liste der Statuscodes wird im Laufe der Zeit möglicherweise erweitert.

Informationen zu Timeouts und Wiederholungsversuchen finden Sie unter Konto für Timeout-Fehler und Berücksichtigen, dass Remotedienst mehr als eine Zeile übergeben kann.

Best Practices

Die folgenden bewährten Methoden gelten für die meisten externen Funktionen, insbesondere für den Remotedienst-Teil.

Eine Zeile nach der anderen verarbeiten

Um den Netzwerkaufwand zu minimieren, fasst Snowflake normalerweise Zeilen in Batches zusammen, um sie an Remotedienste zu senden. Die Anzahl der Batches und die Größe jedes Batches können variieren.

Darüber hinaus kann die Reihenfolge der Batches variieren, und die Reihenfolge der Zeilen innerhalb eines Batches kann variieren. Selbst wenn die Abfrage eine ORDER BY-Klausel enthält, wird ORDER BY normalerweise angewendet, nachdem die externen Funktionen aufgerufen wurden.

Da die Stapelgröße und die Zeilenreihenfolge nicht garantiert werden können, kann das Schreiben einer Funktion, die einen Wert für eine Zeile zurückgibt, der von einer anderen Zeile in diesem Batch oder früheren Batches abhängt, zu nicht deterministischen Ergebnissen führen.

Snowflake empfiehlt dringend, dass der Remotedienst jede Zeile unabhängig verarbeitet. Der Rückgabewert für jede Eingabezeile sollte nur von dieser Eingabezeile abhängen, nicht von anderen Eingabezeilen. (Derzeit unterstützen externe Funktionen beispielsweise keine Fensterfunktionen.)

Beachten Sie außerdem, dass das Zählen von Batches nicht sinnvoll ist, da die Batchgröße nicht garantiert ist.

Siehe auch Nur zustandslose externe Funktionen verwenden.

Berücksichtigen, dass Remotedienst mehr als eine Zeile übergeben kann

Wenn Snowflake einen Remotedienst anruft, und der Remotedienst die Anforderung empfängt und ein Ergebnis zurückgibt, Snowflake aber das Ergebnis aufgrund eines vorübergehenden Netzwerkproblems nicht empfängt, wiederholt Snowflake möglicherweise die Anforderung. Wenn Snowflake es erneut versucht, sieht der Remotedienst möglicherweise zweimal (oder mehrmals) dieselbe Zeile.

Dies kann zu unerwarteten Effekten führen. Da der Remotedienst beispielsweise für denselben Wert möglicherweise mehrmals aufgerufen wird, weist ein Remotedienst, der eindeutige IDs zuweist, möglicherweise Lücken in der Reihenfolge dieser IDs auf.

Snowflake versucht es erneut, wenn die folgenden Fehler angezeigt werden:

  • Alle vorübergehenden Netzwerktransportfehler.

  • Alle Anforderungen, die mit Statuscode 429 fehlschlagen.

  • Alle Anforderungen, die mit Statuscode 5XX fehlschlagen.

Anforderungen werden mit exponentiellem Backoff wiederholt, bis ein Gesamt-Timeout für Wiederholungen erreicht ist. Das Gesamt-Timeout für Wiederholungen ist derzeit nicht dokumentiert und kann nicht vom Benutzer konfiguriert werden. Snowflake kann dieses Limit möglicherweise in Zukunft anpassen.

Wenn das Gesamt-Timeout für Wiederholungen ohne erfolgreiche Wiederholung erreicht ist, schlägt die Abfrage fehl.

Wenn der Aufruf Ihrer externen Funktion mit Timeout fehlschlägt, der Remotedienst aber funktioniert, und alle Elemente zwischen Snowflake und dem Remotedienst zu funktionieren scheinen, können Sie eine geringere Batchgröße probieren, um festzustellen, ob dies die Anzahl der Timeout-Fehler verringert.

Eine Anleitung zum Festlegen der maximalen Batchgröße finden Sie unter CREATE EXTERNAL FUNCTION.

Nur zustandslose externe Funktionen verwenden

Alle Aspekte einer externen Funktion (einschließlich des Remotedienstes) sollten das Speichern von Statusinformationen vermeiden. Dies gilt für:

  • Interner Status (Status, den der Remotedienst intern speichert)

  • Externer Status (Status, der außerhalb des Remotedienstes gespeichert ist, z. B. Statusinformationen, die an einen anderen Remotedienst gesendet und/oder von diesem gelesen werden, der selbst den Status beibehält).

Wenn der Remotedienst Statusinformationen ändert und diese Informationen dann verwendet, um zukünftige Ausgaben zu beeinflussen, gibt die Funktion möglicherweise andere Werte als erwartet zurück.

Stellen Sie sich beispielsweise einen einfachen Remotedienst vor, der einen internen Zähler enthält und die Anzahl der Zeilen zurückgibt, die seit dem ersten Start des Remotedienstes empfangen wurden. Wenn ein vorübergehendes Netzwerkproblem vorliegt und Snowflake eine Anforderung mit denselben Daten wiederholt, zählt der Remotedienst die erneut gesendeten Zeilen zweimal (oder mehrmals).

Ein Beispiel für einen externen Status finden Sie unter Nebeneffekte vermeiden.

In den sehr seltenen Fällen, in denen eine Funktion nicht zustandslos ist, sollte in der Dokumentation deutlich hervorgehoben werden, dass die Funktion nicht zustandslos ist, und die Funktion sollte als „flüchtig“ gekennzeichnet werden.

Nebeneffekte vermeiden

Eine externe Funktion (einschließlich des Remotedienstes) sollte Nebeneffekte wie das Ändern des externen Status (außerhalb des Remotedienstes gespeicherte Informationen) vermeiden.

Wenn der Remotedienst beispielsweise Werte außerhalb des Bereichs an eine Regierungsbehörde meldet, ist dies ein Nebeneffekt.

Nebeneffekte können nützlich sein, aber die Nebeneffekte des Aufrufs einer externen Funktion sind nicht immer vorhersehbar. Angenommen, Sie rufen einen Remotedienst auf, der eine anonymisierte Patientenakte analysiert und eine Diagnose zurückgibt. Angenommen, die Diagnose lautet, dass der Patient eine ansteckende Krankheit hat, dann wird die Diagnose einer Behörde gemeldet, die die Anzahl der Fälle dieser Krankheit zählt. Dies ist ein sinnvoller Nebeneffekt. Er ist jedoch anfällig für folgende Probleme:

  • Befindet sich ein externer Funktionsaufruf in einer Transaktion, die zurückgesetzt wird, werden die Nebenwirkungen nicht zurückgesetzt.

  • Wenn der Remotedienst mehrmals mit derselben Zeile aufgerufen wird (z. B. aufgrund vorübergehender Netzwerkfehler und erneuter Versuche), kann der Nebeneffekt mehrmals auftreten. Im Beispiel wird dann ein infizierter Patient in der Statistik mehrfach gezählt.

Es gibt auch Situationen, in denen eher zu wenige als zu viele Zeilen gezählt werden können.

In den sehr seltenen Fällen, in denen eine Funktion Nebeneffekte hat, sollte in der Dokumentation deutlich benannt werden, welche Nebeneffekte dies sind, und die Funktion sollte als „flüchtig“ gekennzeichnet werden.

Funktion als „Flüchtig“ oder „Unveränderlich“ kategorisieren

Funktionen können als flüchtig oder unveränderlich eingestuft werden. (Mit der Anweisung CREATE EXTERNAL FUNCTION kann der Benutzer angeben, ob die Funktion flüchtig oder unveränderlich ist.)

Damit eine externe Funktion als unveränderlich angesehen werden kann, sollte sie die folgenden Kriterien erfüllen:

  • Bei gleichem Eingabewert gibt die Funktion denselben Ausgabewert zurück. (Während beispielsweise die Funktion SQRT für dieselben Eingabewerte immer dieselben Ausgabewerte zurückgibt, ist dies bei der Funktion CURRENT_TIMESTAMP nicht notwendigerweise so.)

  • Die Funktion hat keine Nebeneffekte.

Wenn eine Funktion diese beiden Kriterien erfüllt, kann Snowflake bestimmte Arten von Optimierungen vornehmen, um die Anzahl der an den Remotedienst gesendeten Zeilen oder Batches zu verringern. (Diese Optimierungen werden im Laufe der Zeit möglicherweise weiterentwickelt und werden hier nicht im Detail beschrieben.)

Snowflake kann Unveränderlichkeit oder Faktoren, die die Unveränderlichkeit beeinflussen (z. B. Nebeneffekte), weder erkennen noch erzwingen. Der Ersteller eines Remotedienstes sollte dokumentieren, ob der Remotedienst die Kriterien für „Unveränderlichkeit“ erfüllt. Wenn ein Remotedienst Nebeneffekte hat, sollte die externe Funktion, die diesen Remotedienst aufruft, als flüchtig gekennzeichnet werden, auch wenn der Funktionsaufruf denselben Ausgabewert für denselben Eingabewert zurückgibt. Wenn Sie nicht sicher sind, ob ein Remotedienst unveränderlich ist, sollte jede externe Funktion, die diesen Remotedienst aufruft, als flüchtig gekennzeichnet werden.

Konto für Timeout-Fehler

Der Aufruf einer externen Funktion hat Auswirkungen auf Snowflake, einen Remotedienst, einen Proxydienst und möglicherweise andere Elemente in der Verarbeitungsabfolge. Keines dieser Elemente weiß, wie lange ein bestimmter Funktionsaufruf dauern soll, daher weiß keines genau, wann das Warten beendet und ein Timeout-Fehler zurückgegeben werden muss. Jeder Schritt kann einen eigenen, unabhängigen Timeoutwert haben. Weitere Informationen zu Timeouts finden Sie unter Berücksichtigen, dass Remotedienst mehr als eine Zeile übergeben kann.

Minimieren der Latenz

Um die Latenz zu minimieren und die Verarbeitungsleistung externer Funktionen zu verbessern, empfiehlt Snowflake ggf. folgende Maßnahmen:

  • Verwenden Sie das API Gateway auf derselben Cloudplattform derselben Region wie die Snowflake-Instanzen, die es am häufigsten (oder mit der größten Datenmenge) aufrufen.

  • Wenn Sie den Remotedienst selbst geschrieben haben (anstatt einen vorhandenen Dienst zu verwenden), stellen Sie diesen Remotedienst auf derselben Cloudplattform derselben Region bereit, von der aus er aufgerufen wird.

  • Senden Sie so wenige Daten wie möglich. Wenn der Remotedienst beispielsweise Eingabewerte untersucht und nur eine Teilmenge davon verarbeitet, ist es normalerweise effizienter, in SQL zu filtern und nur die relevanten Zeilen an den Remotedienst zu senden, anstatt alle Zeilen an den Remotedienst zu senden und von diesem filtern zu lassen.

    Wenn Sie als weiteres Beispiel eine Spalte verarbeiten, die große semistrukturierte Datenwerte enthält und der Remotedienst nur einen kleinen Teil dieser Datenwerte verarbeitet, ist es normalerweise effizienter, vor der Verarbeitung den relevanten Teil mit Snowflake-SQL zu extrahieren und nur diesen Teil zu senden, anstatt die gesamte Spalte zu senden und das Extrahieren des kleinen Teils vom Remotedienst vornehmen zu lassen.

Externe Funktionen entwickeln und testen

Snowflake empfiehlt, dass Sie vor dem Testen mit Snowflake erst ohne Snowflake testen.

Verwenden Sie in den frühen Phasen der Entwicklung einer externen Funktion die Proxydienst-Konsole der Cloudplattform (z. B. die AWS API Gateway-Konsole) und die Remotedienst-Entwicklungskonsole (z. B. die AWS Lambda-Konsole), um den Proxydienst und den Remotedienst zu entwickeln und zu testen.

Wenn Sie beispielsweise eine Lambda-Funktion entwickelt haben, sollten Sie diese erst ausführlich über die Lambda-Konsole testen, bevor Sie sie über Snowflake aufrufen.

Das Testen über Proxydienst-Konsole und Remotedienst-Konsole bietet normalerweise die folgenden Vorteile:

  • Die Diagnose von Problemen wird erleichtert, da weniger potenzielle Quellen als Ursache des Problems in Frage kommen und untersucht werden müssen.

  • Das Anzeigen der Datennutzlast bietet möglicherweise hilfreiche Informationen für das Debugging. Snowflake zeigt in Fehlermeldungen keine Ausschnitte der Datennutzlast an. Dies erhöht zwar die Sicherheit, kann jedoch das Debuggen verlangsamen.

  • Snowflake wiederholt HTTP-5xx-Fehler automatisch, was das Debuggen in einigen Situationen langsamer oder schwieriger machen kann.

  • Das Testen über Snowflake verbraucht zusätzlich zu den Credits für die Cloudplattform auch Snowflake-Credits.

Nachdem Sie Remotedienst und Proxydienst so häufig wie möglich ohne Snowflake getestet haben, sollten Sie die Dienste natürlich auch mit Snowflake testen. Die Testen mit Snowflake bietet folgende Vorteile:

  • Sie testen alle Schritte der externen Funktion.

  • Die Verwendung einer Snowflake-Tabelle als Datenquelle erleichtert das Testen mit großen Datenmengen, um eine realistische Schätzung der Leistung der externen Funktion zu erhalten.

Betrachten Sie die folgenden Testfälle:

  • NULL-Werte

  • „Leere“ Werte (z. B. leere Zeichenfolgen, leere semistrukturierte Datentypen).

  • Gegebenenfalls sehr lange VARCHAR- und BINARY-Werte.

Proxydienst

Proxydienst-Endpunkt sichern

Snowflake empfiehlt dringend die Sicherung Ihrer Proxydienst-Endpunkte.

Snowflake verwendet API-Integrationsobjekte ohne Anmeldeinformationen, um sich beim Proxydienst-Endpunkt zu authentifizieren. API-Integrationen ohne Anmeldeinformationen sorgen dafür, dass Verantwortlichkeiten zwischen Administratoren und Benutzern aufgeteilt werden. Durch eine API-Integration kann ein Administrator mithilfe des nativen Authentifizierungs- und Autorisierungsmechanismus des Cloudanbieters eine Vertrauensrichtlinie zwischen Snowflake und dem Cloudanbieter erstellen. Wenn Snowflake eine Verbindung zum Cloudanbieter herstellt, authentifiziert und autorisiert der Cloudanbieter den Zugriff über diese Vertrauensrichtlinie. Mithilfe einer speziellen API-Integration kann der Administrator auch einschränken, welche Proxydienste und Ressourcen Snowflake verwenden kann, sodass der Administrator Organisationsrichtlinien für den Datenausgang und -eingang durchsetzen kann.

Detaillierte Anleitungen zum Sichern bestimmter Proxydienst-Endpunkte, z. B. eines AWS API Gateways, finden Sie in den plattformspezifischen Anweisungen.