Arbeiten mit asynchronen untergeordneten Aufträgen¶
In diesem Thema wird erklärt, wie Sie asynchrone untergeordnete Aufträge in Snowflake Scripting verwenden.
Einführung in asynchrone untergeordnete Aufträge¶
In Snowflake Scripting ist ein asynchroner untergeordneter Auftrag eine Abfrage, die im Hintergrund ausgeführt wird, während der Code in einem Block weiterläuft. Die Abfrage kann jede gültige SQL-Anweisung sein, einschließlich SELECT-Anweisungen und DML-Anweisungen wie INSERT oder UPDATE.
Um eine Abfrage als asynchronen untergeordneten Auftrag auszuführen, setzen Sie das Schlüsselwort ASYNC vor die Abfrage. Wenn dieses Schlüsselwort weggelassen wird, führt der Snowflake Scripting-Block die untergeordneten Aufträge nacheinander aus und jeder untergeordnete Auftrag wartet auf das Ende des laufenden untergeordneten Auftrags, bevor er beginnt. Asynchrone untergeordnete Aufträge können gleichzeitig ausgeführt werden, was die Effizienz verbessern und die Gesamtlaufzeit verkürzen kann.
Sie können das Schlüsselwort ASYNC auf die folgenden Arten verwenden:
Für eine Abfrage, die für ein RESULTSET ausgeführt wird.
Für eine Abfrage, die unabhängig von einem RESULTSET ausgeführt wird.
Um asynchrone untergeordnete Aufträge zu verwalten, verwenden Sie die Anweisungen AWAIT und CANCEL:
Die Anweisung AWAIT wartet auf die Beendigung aller laufenden asynchronen untergeordneten Aufträge oder auf die Beendigung eines bestimmten untergeordneten Auftrags, der für ein RESULTSET läuft, und kehrt dann zurück, wenn alle Aufträge bzw. der bestimmte Auftrag beendet sind.
Die Anweisung CANCEL bricht einen asynchronen untergeordneten Auftrag ab, der für ein RESULTSET läuft.
Sie können den Status eines asynchronen untergeordneten Auftrags, der für ein RESULTSET läuft, überprüfen, indem Sie die Funktion SYSTEM$GET_RESULTSET_STATUS aufrufen.
Derzeit können bis zu 4.000 asynchrone untergeordnete Aufträge gleichzeitig ausgeführt werden. Ein Fehler wird zurückgegeben, wenn die Anzahl der gleichzeitigen asynchronen untergeordneten Aufträge diese Grenze überschreitet.
Bemerkung
Wenn mehrere asynchrone untergeordnete Aufträge gleichzeitig in derselben Sitzung ausgeführt werden, ist die Reihenfolge der Beendigung des Auftrags erst bekannt, wenn die Aufträge abgeschlossen sind. Da die Reihenfolge der Fertigstellung variieren kann, ist die Verwendung der Funktion LAST_QUERY_ID mit asynchronen untergeordneten Aufträgen nicht deterministisch.
Beispiele für die Verwendung asynchroner untergeordneter Aufträge¶
In den folgenden Abschnitten finden Sie Beispiele für die Verwendung asynchroner untergeordneter Aufträge:
Beispiel: Ausführen von untergeordneten Jobs mit gleichzeitiger Abfrage von Tabellen
Beispiel: Ausführen von untergeordneten Jobs, die gleichzeitig Zeilen in Tabellen einfügen
Beispiel: Untergeordnete Aufträge für Einfügungen in einer Schleife ausführen
Beispiel: Ausführen von untergeordneten Jobs mit gleichzeitiger Abfrage von Tabellen¶
Der folgende Code zeigt, wie Sie das Schlüsselwort ASYNC verwenden, um mehrere untergeordnete Jobs auszuführen, die gleichzeitig Tabellen abfragen. Das Beispiel gibt das Schlüsselwort ASYNC für Abfragen an, die für RESULTSETs ausgeführt werden.
Dieses Beispiel verwendet die Daten in den folgenden Tabellen:
CREATE OR REPLACE TABLE orders_q1_2024 (
order_id INT,
order_amount NUMBER(12,2));
INSERT INTO orders_q1_2024 VALUES (1, 500.00);
INSERT INTO orders_q1_2024 VALUES (2, 225.00);
INSERT INTO orders_q1_2024 VALUES (3, 725.00);
INSERT INTO orders_q1_2024 VALUES (4, 150.00);
INSERT INTO orders_q1_2024 VALUES (5, 900.00);
CREATE OR REPLACE TABLE orders_q2_2024 (
order_id INT,
order_amount NUMBER(12,2));
INSERT INTO orders_q2_2024 VALUES (1, 100.00);
INSERT INTO orders_q2_2024 VALUES (2, 645.00);
INSERT INTO orders_q2_2024 VALUES (3, 275.00);
INSERT INTO orders_q2_2024 VALUES (4, 800.00);
INSERT INTO orders_q2_2024 VALUES (5, 250.00);
Die folgende gespeicherte Prozedur führt die folgenden Aktionen aus:
Fragt beide Tabellen nach den
order_amount
-Werten in allen Zeilen ab und gibt die Ergebnisse an verschiedene RESULTSETs zurück (eins für jede Tabelle).Legt fest, dass die Abfragen als gleichzeitige untergeordnete Jobs ausgeführt werden, indem Sie das Schlüsselwort ASYNC verwenden.
Führt die AWAIT-Anweisung für jedes RESULTSET aus, sodass die Prozedur wartet, bis die Abfragen beendet sind, bevor sie fortfährt. Auf die Abfrageergebnisse für ein RESULTSET kann erst zugegriffen werden, wenn AWAIT für das RESULTSET ausgeführt wird.
Verwendet einen Cursor, um die Summe der
order_amount
-Zeilen für jede Tabelle zu berechnen.Addiert die Summen für die Tabellen und gibt den Wert zurück.
CREATE OR REPLACE PROCEDURE test_sp_async_child_jobs_query()
RETURNS INTEGER
LANGUAGE SQL
AS
DECLARE
accumulator1 INTEGER DEFAULT 0;
accumulator2 INTEGER DEFAULT 0;
res1 RESULTSET DEFAULT ASYNC (SELECT order_amount FROM orders_q1_2024);
res2 RESULTSET DEFAULT ASYNC (SELECT order_amount FROM orders_q2_2024);
BEGIN
AWAIT res1;
LET cur1 CURSOR FOR res1;
OPEN cur1;
AWAIT res2;
LET cur2 CURSOR FOR res2;
OPEN cur2;
FOR row_variable IN cur1 DO
accumulator1 := accumulator1 + row_variable.order_amount;
END FOR;
FOR row_variable IN cur2 DO
accumulator2 := accumulator2 + row_variable.order_amount;
END FOR;
RETURN accumulator1 + accumulator2;
END;
Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die Classic Console, oder die Methode execute_stream
oder execute_string
in Python Connector Code verwenden, benutzen Sie stattdessen dieses Beispiel (siehe Verwenden von Snowflake Scripting in Snowflake CLI, SnowSQL, Classic Console und im Python-Connector):
CREATE OR REPLACE PROCEDURE test_sp_async_child_jobs_query()
RETURNS INTEGER
LANGUAGE SQL
AS
$$
DECLARE
accumulator1 INTEGER DEFAULT 0;
accumulator2 INTEGER DEFAULT 0;
res1 RESULTSET DEFAULT ASYNC (SELECT order_amount FROM orders_q1_2024);
res2 RESULTSET DEFAULT ASYNC (SELECT order_amount FROM orders_q2_2024);
BEGIN
AWAIT res1;
LET cur1 CURSOR FOR res1;
OPEN cur1;
AWAIT res2;
LET cur2 CURSOR FOR res2;
OPEN cur2;
FOR row_variable IN cur1 DO
accumulator1 := accumulator1 + row_variable.order_amount;
END FOR;
FOR row_variable IN cur2 DO
accumulator2 := accumulator2 + row_variable.order_amount;
END FOR;
RETURN accumulator1 + accumulator2;
END;
$$;
Rufen Sie die gespeicherte Prozedur auf:
CALL test_sp_async_child_jobs_query();
+--------------------------------+
| TEST_SP_ASYNC_CHILD_JOBS_QUERY |
|--------------------------------|
| 4570 |
+--------------------------------+
Beispiel: Ausführen von untergeordneten Jobs, die gleichzeitig Zeilen in Tabellen einfügen¶
Der folgende Code zeigt, wie Sie das Schlüsselwort ASYNC verwenden, um mehrere untergeordnete Jobs auszuführen, die gleichzeitig Zeilen in eine Tabelle einfügen. Das Beispiel gibt das Schlüsselwort ASYNC für Abfragen an, die für RESULTSETs ausgeführt werden.
Die folgende gespeicherte Prozedur führt die folgenden Aktionen aus:
Erstellt die Tabelle
orders_q3_2024
, wenn sie nicht existiert.Erzeugt zwei RESULTSETs,
insert_1
undinsert_2
, die die Ergebnisse von Einfügungen in die Tabelle enthalten. Die Argumente der gespeicherten Prozedur geben die Werte an, die in die Tabelle eingefügt werden.Legt fest, dass die Einfügungen als gleichzeitige untergeordnete Jobs ausgeführt werden, indem Sie das Schlüsselwort ASYNC verwenden.
Führt die AWAIT-Anweisung für jedes RESULTSET aus, sodass die Prozedur wartet, bis die Einfügungen beendet sind, bevor sie fortfährt. Auf die Ergebnisse eines RESULTSET kann erst zugegriffen werden, wenn AWAIT für das RESULTSET ausgeführt wird.
Erzeugt eine neues RESULTSET
res
, das die Ergebnisse einer Abfrage in der Tabelleorders_q3_2024
enthält.Gibt die Ergebnisse der Abfrage zurück.
CREATE OR REPLACE PROCEDURE test_sp_async_child_jobs_insert(
arg1 INT,
arg2 NUMBER(12,2),
arg3 INT,
arg4 NUMBER(12,2))
RETURNS TABLE()
LANGUAGE SQL
AS
BEGIN
CREATE TABLE IF NOT EXISTS orders_q3_2024 (
order_id INT,
order_amount NUMBER(12,2));
LET insert_1 RESULTSET := ASYNC (INSERT INTO orders_q3_2024 SELECT :arg1, :arg2);
LET insert_2 RESULTSET := ASYNC (INSERT INTO orders_q3_2024 SELECT :arg3, :arg4);
AWAIT insert_1;
AWAIT insert_2;
LET res RESULTSET := (SELECT * FROM orders_q3_2024 ORDER BY order_id);
RETURN TABLE(res);
END;
Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die Classic Console, oder die Methode execute_stream
oder execute_string
in Python Connector Code verwenden, benutzen Sie stattdessen dieses Beispiel (siehe Verwenden von Snowflake Scripting in Snowflake CLI, SnowSQL, Classic Console und im Python-Connector):
CREATE OR REPLACE PROCEDURE test_sp_async_child_jobs_insert(
arg1 INT,
arg2 NUMBER(12,2),
arg3 INT,
arg4 NUMBER(12,2))
RETURNS TABLE()
LANGUAGE SQL
AS
$$
BEGIN
CREATE TABLE IF NOT EXISTS orders_q3_2024 (
order_id INT,
order_amount NUMBER(12,2));
LET insert_1 RESULTSET := ASYNC (INSERT INTO orders_q3_2024 SELECT :arg1, :arg2);
LET insert_2 RESULTSET := ASYNC (INSERT INTO orders_q3_2024 SELECT :arg3, :arg4);
AWAIT insert_1;
AWAIT insert_2;
LET res RESULTSET := (SELECT * FROM orders_q3_2024 ORDER BY order_id);
RETURN TABLE(res);
END;
$$;
Rufen Sie die gespeicherte Prozedur auf:
CALL test_sp_async_child_jobs_insert(1, 325, 2, 241);
+----------+--------------+
| ORDER_ID | ORDER_AMOUNT |
|----------+--------------|
| 1 | 325.00 |
| 2 | 241.00 |
+----------+--------------+
Beispiel: Ausführen von untergeordneten Aufträgen in gespeicherten Prozeduren mit AWAIT ALL-Anweisungen¶
In den folgenden Beispielen wird das Schlüsselwort ASYNC verwendet, um mehrere untergeordnete Aufträge gleichzeitig in gespeicherten Prozeduren auszuführen. Die Beispiele geben das Schlüsselwort ASYNC für Anweisungen an, die nicht mit einem RESULTSET verbunden sind, und verwenden dann die Anweisung AWAIT ALL, damit der gespeicherte Prozedurcode auf den Abschluss aller asynchronen untergeordneten Aufträge wartet.
Erstellen Sie eine gespeicherte Prozedur, die Werte gleichzeitig einfügt
Erstellen Sie eine gespeicherte Prozedur, die Werte gleichzeitig aktualisiert
Erstellen Sie eine gespeicherte Prozedur, die gleichzeitig andere gespeicherte Prozeduren aufruft
Erstellen Sie eine gespeicherte Prozedur, die Werte gleichzeitig einfügt¶
Die folgende gespeicherte Prozedur verwendet das Schlüsselwort ASYNC, um mehrere untergeordnete Aufträge auszuführen, die gleichzeitig Zeilen in eine Tabelle einfügen. Das Beispiel gibt das Schlüsselwort ASYNC für die Anweisungen INSERT an. Das Beispiel verwendet auch die Anweisung AWAIT ALL, damit die gespeicherte Prozedur auf den Abschluss aller asynchronen untergeordneten Aufträge wartet.
CREATE OR REPLACE PROCEDURE test_async_child_job_inserts()
RETURNS VARCHAR
LANGUAGE SQL
AS
BEGIN
CREATE OR REPLACE TABLE test_child_job_queries1 (col1 INT);
ASYNC (INSERT INTO test_child_job_queries1(col1) VALUES(1));
ASYNC (INSERT INTO test_child_job_queries1(col1) VALUES(2));
ASYNC (INSERT INTO test_child_job_queries1(col1) VALUES(3));
AWAIT ALL;
END;
Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die Classic Console, oder die Methode execute_stream
oder execute_string
in Python Connector Code verwenden, benutzen Sie stattdessen dieses Beispiel (siehe Verwenden von Snowflake Scripting in Snowflake CLI, SnowSQL, Classic Console und im Python-Connector):
CREATE OR REPLACE PROCEDURE test_async_child_job_inserts()
RETURNS VARCHAR
LANGUAGE SQL
AS
$$
BEGIN
CREATE OR REPLACE TABLE test_child_job_queries1 (col1 INT);
ASYNC (INSERT INTO test_child_job_queries1(col1) VALUES(1));
ASYNC (INSERT INTO test_child_job_queries1(col1) VALUES(2));
ASYNC (INSERT INTO test_child_job_queries1(col1) VALUES(3));
AWAIT ALL;
END;
$$
;
Erstellen Sie eine gespeicherte Prozedur, die Werte gleichzeitig aktualisiert¶
Die folgende gespeicherte Prozedur verwendet das Schlüsselwort ASYNC, um mehrere untergeordnete Aufträge auszuführen, die gleichzeitig Zeilen in einer Tabelle aktualisieren. Das Beispiel gibt das Schlüsselwort ASYNC für die Anweisungen UPDATE an. Das Beispiel verwendet auch die Anweisung AWAIT ALL, damit die gespeicherte Prozedur auf den Abschluss aller asynchronen untergeordneten Aufträge wartet.
Erstellen Sie eine Tabelle, und fügen Sie Daten ein:
CREATE OR REPLACE TABLE test_child_job_queries2 (id INT, cola INT);
INSERT INTO test_child_job_queries2 VALUES
(1, 100), (2, 101), (3, 102);
Erstellen Sie die gespeicherte Prozedur:
CREATE OR REPLACE PROCEDURE test_async_child_job_updates()
RETURNS VARCHAR
LANGUAGE SQL
AS
BEGIN
ASYNC (UPDATE test_child_job_queries2 SET cola=200 WHERE id=1);
ASYNC (UPDATE test_child_job_queries2 SET cola=201 WHERE id=2);
ASYNC (UPDATE test_child_job_queries2 SET cola=202 WHERE id=3);
AWAIT ALL;
END;
Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die Classic Console, oder die Methode execute_stream
oder execute_string
in Python Connector Code verwenden, benutzen Sie stattdessen dieses Beispiel (siehe Verwenden von Snowflake Scripting in Snowflake CLI, SnowSQL, Classic Console und im Python-Connector):
CREATE OR REPLACE PROCEDURE test_async_child_job_updates()
RETURNS VARCHAR
LANGUAGE SQL
AS
$$
BEGIN
ASYNC (UPDATE test_child_job_queries2 SET cola=200 WHERE id=1);
ASYNC (UPDATE test_child_job_queries2 SET cola=201 WHERE id=2);
ASYNC (UPDATE test_child_job_queries2 SET cola=202 WHERE id=3);
AWAIT ALL;
END;
$$
;
Erstellen Sie eine gespeicherte Prozedur, die gleichzeitig andere gespeicherte Prozeduren aufruft¶
CREATE OR REPLACE PROCEDURE test_async_child_job_calls()
RETURNS VARCHAR
LANGUAGE SQL
AS
BEGIN
ASYNC (CALL test_async_child_job_inserts());
ASYNC (CALL test_async_child_job_updates());
AWAIT ALL;
END;
Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die Classic Console, oder die Methode execute_stream
oder execute_string
in Python Connector Code verwenden, benutzen Sie stattdessen dieses Beispiel (siehe Verwenden von Snowflake Scripting in Snowflake CLI, SnowSQL, Classic Console und im Python-Connector):
CREATE OR REPLACE PROCEDURE test_async_child_job_calls()
RETURNS VARCHAR
LANGUAGE SQL
AS
$$
BEGIN
ASYNC (CALL test_async_child_job_inserts());
ASYNC (CALL test_async_child_job_updates());
AWAIT ALL;
END;
$$
;
Rufen Sie die gespeicherte Prozedur test_async_child_job_calls
auf:
CALL test_async_child_job_calls();
Fragen Sie die Tabellen ab, um die Ergebnisse zu sehen:
SELECT col1 FROM test_child_job_queries1 ORDER BY col1;
+------+
| COL1 |
|------|
| 1 |
| 2 |
| 3 |
+------+
SELECT * FROM test_child_job_queries2 ORDER BY id;
+----+------+
| ID | COLA |
|----+------|
| 1 | 200 |
| 2 | 201 |
| 3 | 202 |
+----+------+
Beispiel: Untergeordnete Aufträge für Einfügungen in einer Schleife ausführen¶
Der folgende Code zeigt, wie Sie das Schlüsselwort ASYNC in einer Schleife verwenden, um mehrere untergeordnete Aufträge auszuführen, die gleichzeitig Zeilen in eine Tabelle einfügen.
Dieses Beispiel verwendet die Daten in den folgenden Tabellen:
CREATE OR REPLACE TABLE async_loop_test1(col1 VARCHAR, col2 INT);
INSERT INTO async_loop_test1 VALUES
('child', 0),
('job', 1),
('loop', 2),
('test', 3);
CREATE OR REPLACE TABLE async_loop_test2(col1 INT, col2 VARCHAR);
Erstellen Sie eine gespeicherte Prozedur, die Werte aus async_loop_test1
, verkettet mit dem Text async_
in async_loop_test2
unter Verwendung asynchroner untergeordneter Jobs in eine FOR Schleife einfügt. Die Schleife erstellt bei jeder Iteration einen separaten asynchronen untergeordneten Auftrag. Die Anweisung AWAIT ALL blockiert den Fortschritt in der gespeicherten Prozedur, bis alle untergeordneten Aufträge erledigt sind.
CREATE OR REPLACE PROCEDURE async_insert()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
begin
LET res RESULTSET := (SELECT * FROM async_loop_test1 ORDER BY 1);
FOR record IN res DO
LET v VARCHAR := record.col1;
LET x INT := record.col2;
ASYNC (INSERT INTO async_loop_test2(col1, col2) VALUES (:x, (SELECT 'async_' || :v)));
END FOR;
AWAIT ALL;
RETURN 'Success';
END;
Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die Classic Console, oder die Methode execute_stream
oder execute_string
in Python Connector Code verwenden, benutzen Sie stattdessen dieses Beispiel (siehe Verwenden von Snowflake Scripting in Snowflake CLI, SnowSQL, Classic Console und im Python-Connector):
CREATE OR REPLACE PROCEDURE async_insert()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
begin
LET res RESULTSET := (SELECT * FROM async_loop_test1 ORDER BY 1);
FOR record IN res DO
LET v VARCHAR := record.col1;
LET x INT := record.col2;
ASYNC (INSERT INTO async_loop_test2(col1, col2) VALUES (:x, (SELECT 'async_' || :v)));
END FOR;
AWAIT ALL;
RETURN 'Success';
END;
$$;
Rufen Sie die gespeicherte Prozedur auf:
CALL async_insert();
+--------------+
| ASYNC_INSERT |
|--------------|
| Success |
+--------------+
Fragen Sie die Tabelle async_loop_test2
ab, um die Ergebnisse zu sehen:
SELECT * FROM async_loop_test2 ORDER BY col1;
+------+-------------+
| COL1 | COL2 |
|------+-------------|
| 0 | async_child |
| 1 | async_job |
| 2 | async_loop |
| 3 | async_test |
+------+-------------+