JavaScript-UDF-Einschränkungen

Um die Stabilität in der Snowflake-Umgebung sicherzustellen, hat Snowflake folgende Einschränkungen für JavaScript-UDFs definiert. Diese Einschränkungen werden nicht zum Zeitpunkt der UDF-Erstellung aufgerufen, sondern erst zur Laufzeit beim Aufrufen der UDF-Funktion. Unter diesem Thema werden allgemeine Anforderungen an JavaScript-UDFs (benutzerdefinierte Funktionen) sowie Nutzungsdetails und spezifische Einschränkungen für JavaScript-UDFs behandelt.

Unter diesem Thema:

Maximale Größe des JavaScript-Quellcodes

Snowflake begrenzt die maximale Größe des JavaScript-Quellcodes im Textteil einer JavaScript-UDF. Snowflake empfiehlt eine Begrenzung auf 100 KB. (Da der Code in komprimierter Form gespeichert ist, hängt das genaue Limit von der Komprimierbarkeit des Codes ab.)

Zu hoher Verbrauch von Arbeitsspeicher führt zu UDF-Fehler

JavaScript-UDFs werden fehlschlagen, wenn sie zu viel Arbeitsspeicher verbrauchen. Das spezifische Limit kann sich ändern. Wenn zu viel Arbeitsspeicher belegt wird, wird ein Fehler zurückgegeben.

Zu lange Ausführung der UDF führt zu Abbruch und Rückgabe eines Fehlers

JavaScript-UDFs, die zu lange ausgeführt werden, werden beendet, und es wird ein Fehler an den Benutzer zurückgegeben. Zudem führen JavaScript-UDFs, die in Endlosschleifen eintreten, zu einem Fehler.

Übermäßige Stapeltiefe führt zu einem Fehler

Übermäßige Stapeltiefe aufgrund von Rekursion führt zu einem Fehler.

Globaler Status

Snowflake behält normalerweise den globalen JavaScript-Zustand zwischen den Iterationen einer UDF bei. Sie sollten sich jedoch nicht darauf verlassen, dass vorherige Änderungen am globalen Zustand zwischen Funktionsaufrufen verfügbar sind. Außerdem sollten Sie nicht davon ausgehen, dass alle Zeilen in der gleichen JavaScript-Umgebung ausgeführt werden.

In der Praxis ist der globale Status relevant bei:

  • Komplexe/aufwändige Initialisierungslogik. Standardmäßig wird der bereitgestellte UDF-Code für jede verarbeitete Zeile ausgewertet. Wenn der Code komplexe Logik enthält, könnte dies ineffizient sein.

  • Funktionen, die Code enthalten, der nicht idempotent ist. Ein typisches Muster wäre:

    Date.prototype._originalToString = Date.prototype.toString;
    Date.prototype.toString = function() {
      /* ... SOME CUSTOM CODE ... */
      this._originalToString()
      }
    
    Copy

    Bei der ersten Ausführung dieses Codes ändert sich der Zustand von toString und _originalToString. Diese Änderungen werden im globalen Zustand beibehalten. Wenn der Code zum zweiten Mal ausgeführt wird, werden die Werte erneut so geändert, dass eine Rekursion entsteht. Beim zweiten Aufruf von toString wird der Code unendlich oft rekursiert (bis der Stapelspeicherplatz erschöpft ist).

In diesen Situationen sollte sichergestellt werden, dass der relevante Code nur einmal ausgewertet wird, wobei die JavaScript-Semantik für globale Variablen verwendet wird. Beispiel:

var setup = function() {
/* SETUP LOGIC */
};

if (typeof(setup_done) === "undefined") {
  setup();
  setup_done = true;  // setting global variable to true
}
Copy

Beachten Sie, dass dieser Mechanismus nur für die Zwischenspeicherung der Auswirkungen der Codeauswertung geeignet ist. Es kann nicht garantiert werden, dass der globale Kontext nach einer Initialisierung für alle Zeilen erhalten bleibt; daher sollte keine Geschäftslogik davon abhängen.

JavaScript-Bibliotheken

JavaScript-UDFs unterstützen den Zugriff auf die JavaScript-Standardbibliothek. Beachten Sie, dass dadurch viele Objekte und Methoden ausgeschlossen werden, die normalerweise von Browsern bereitgestellt werden. Es gibt keinen Mechanismus zum Importieren, Einschließen oder Aufrufen zusätzlicher Bibliotheken. Der gesamte erforderliche Code sollte in der UDF eingebettet sein.

Darüber hinaus ist die integrierte JavaScript-eval()-Funktion deaktiviert.

Zurückgegebene Variant-Größe und -Tiefe

Zurückgegebene Variant-Objekte unterliegen Größen- und Verschachtelungstiefenbeschränkungen:

Größe

Derzeit auf mehrere Megabyte beschränkt, Änderungen vorbehalten.

Tiefe

Derzeit auf eine Schachtelungstiefe von 1.000 begrenzt, Änderungen vorbehalten.

Wenn ein Objekt zu groß oder zu tief ist, wird beim Aufruf der UDF ein Fehler zurückgegeben.

Einschränkungen bei Argument- und Rückgabetypen werden manchmal ignoriert

Bestimmte Typmerkmale, die für ein Argument oder einen Rückgabewert deklariert wurden, werden beim Aufruf der UDF ignoriert. In diesen Fällen kann der zurückgegebene Wert so verwendet werden, wie er erhalten wurde, unabhängig davon, ob er den in der Deklaration angegebenen Einschränkungen entspricht oder nicht.

Die folgenden Angaben werden bei UDFs ignoriert, deren Logik in JavaScript geschrieben ist:

  • Länge für Argumente des Typs VARCHAR

Beispiel

Der Code im folgenden Beispiel deklariert, dass das Argument arg1 und der Rückgabewert VARCHAR nicht länger als ein Zeichen sein dürfen. Wenn Sie diese Funktion jedoch mit einem Argument arg1 aufrufen, dessen Wert länger als ein Zeichen ist, wird die Funktion so ausgeführt, als ob die Einschränkung nicht angegeben wäre.

CREATE OR REPLACE FUNCTION tf (arg1 VARCHAR(1))
RETURNS VARCHAR(1)
LANGUAGE JAVASCRIPT AS 'return A.substr(3, 3);';
Copy