Best Practices für externe Funktionen

Unter diesem Thema sind bewährte Verfahren dokumentiert, die die Effizienz verbessern und unerwartete Ergebnisse verhindern, die auftreten können, wenn ein Remotedienst nicht für die Kompatibilität mit Snowflake entwickelt wurde.

Weitere Best Practices finden Sie in den folgenden Dokumenten:

Unter diesem Thema:

Verwenden Sie, falls verfügbar, die Batch-API des Remotedienstes

Einige Remotedienste bieten sowohl den Batchmodus als auch den Einzelmodus an. Wenn erwartet wird, dass Abfragen, die eine externe Funktion verwenden, mehrere Zeilen senden, dann empfiehlt Snowflake die Verwendung des Batchmodus des Remotedienstes, um die Leistung zu verbessern.

Diese Regel gilt nicht unbedingt in folgenden Situationen:

  • Jede Zeile ist sehr groß (z. B. Hunderte von Kilobytes oder mehr).

  • Der Remotedienst verarbeitet Zeilen anders, wenn sie im Batch empfangen werden, als wenn sie einzeln empfangen werden. (Weitere Details dazu finden Sie unter Eine Zeile nach der anderen verarbeiten.)

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 Sequenz dieser IDs auf. In einigen Fällen können solche Effekte reduziert werden, indem die Batch-ID im Feld sf-external-function-query-batch-id des Anforderungskopfs verfolgt wird, um festzustellen, ob ein bestimmter Batch von Zeilen bereits früher verarbeitet wurde. Wenn Snowflake eine Anforderung für einen bestimmten Batch erneut sendet, verwendet Snowflake die gleiche Batch-ID, die zuvor für denselben Batch verwendet wurde.

Bei Rückgabe der folgenden Fehler sendet Snowflake die Anforderung erneut:

  • Alle vorübergehenden Netzwerktransportfehler.

  • Alle Anforderungen, die mit Statuscode 429 fehlschlagen.

  • Alle Anforderungen, die mit Statuscode 5XX fehlschlagen.

Anforderungen werden wiederholt, bis ein Gesamt-Timeout für Wiederholungen erreicht ist. Das Gesamt-Timeout für Wiederholungen kann vom Benutzer nicht 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

Im Allgemeinen sollte eine externe Funktion (einschließlich des Remotedienstes) 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 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.

Wenn ein Remotedienst Anforderungen asynchron verarbeitet, muss der Autor des Remotedienstes den Remotedienst so schreiben, dass ein Status vorübergehend gespeichert und verwaltet werden kann. Der Remotedienst muss z. B. die Batch-ID der HTTP-POST-Anforderung speichern, damit der Remotedienst, wenn ein HTTP-GET mit demselben Batch-ID empfangen wird, den HTTP-Code 202 zurückgeben kann, während der angegebene Batch noch verarbeitet wird.

Beachten Sie, dass eine Abfrage aus verschiedenen Gründen abgebrochen werden kann, was bedeutet, dass es keine Garantie dafür gibt, dass ein abschließender GET eintrifft, nachdem der Remotedienst die Generierung eines Ergebnisses abgeschlossen hat. Remotedienste, die den Status für asynchrone Anforderungen speichern, sollten irgendwann ein Timeout durchführen und diesen internen Status bereinigen. Das optimale Timeout könnte sich in Zukunft ändern, aber derzeit empfiehlt Snowflake, Informationen über asynchrone Anforderungen mindestens 10 Minuten und vorzugsweise 12 Stunden aufzubewahren, bevor sie gelöscht 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. (Weitere Details dazu finden Sie unter Nebeneffekte vermeiden.)

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 und Wiederholungsversuchen finden Sie unter Konto für Timeout-Fehler und Wiederholungsversuche.

Latenz minimieren

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 Schritt für Schritt 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 Amazon 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 große VARCHAR- und BINARY-Werte.

Zu asynchronem Remotedienst wechseln

Wenn Sie einen Remotedienst schreiben und dieser möglicherweise nicht innerhalb des erwarteten Timeouts Ergebnisse zurückgibt, sollten Sie erwägen, Ihren Remotedienst asynchron auszuführen. Weitere Details dazu finden Sie unter Asynchrone vs. synchrone Remotedienste.

Sicherstellen, dass Argumente der externen Funktion den Argumenten des Remotedienstes entsprechen

Achten Sie beim Übergeben von Argumenten an oder von einer externen Funktion darauf, dass die passenden Datentypen verwendet werden. Wenn der gesendete Wert nicht zum Datentyp des Empfängers passt, wird der Wert möglicherweise abgeschnitten oder beschädigt, oder der Remotedienstaufruf schlägt fehl.

Da z. B. einige numerische Datentypen von Snowflake SQL größere Werte speichern können als häufig verwendete JavaScript-Datentypen, ist die Deserialisierung großer Zahlen von JSON in JavaScript besonders empfindlich.

Wenn Sie die Anzahl, die Datentypen oder die Reihenfolge der Argumente für den Remotedienst ändern, müssen Sie die entsprechenden Änderungen auch an der externen Funktion vornehmen. Derzeit bietet der ALTER FUNCTION-Befehl keine Option zum Ändern von Parametern. Sie müssen daher die externe Funktion löschen und neu erstellen, um die Argumente zu ändern.