{"id":30350,"date":"2025-02-19T05:00:00","date_gmt":"2025-02-19T04:00:00","guid":{"rendered":"https:\/\/sii.pl\/blog\/?p=30350"},"modified":"2025-02-12T12:36:24","modified_gmt":"2025-02-12T11:36:24","slug":"orkiestracja-za-pomoca-snowflake-tasks","status":"publish","type":"post","link":"https:\/\/sii.pl\/blog\/orkiestracja-za-pomoca-snowflake-tasks\/","title":{"rendered":"Orkiestracja za pomoc\u0105 Snowflake Tasks"},"content":{"rendered":"\n<p>Im d\u0142u\u017cej pracuj\u0119 ze Snowflake, tym bardziej si\u0119 w nim zakochuj\u0119. Na pocz\u0105tku my\u015bla\u0142em, \u017ce to tylko nast\u0119pna us\u0142uga hurtowni danych w chmurze. Dlaczego wi\u0119c powinienem si\u0119 ni\u0105 przejmowa\u0107, skoro mam us\u0142ugi data lake i prawie ka\u017cda z nich udost\u0119pnia jak\u0105\u015b ko\u0144c\u00f3wk\u0119 (endpoint) SQL? A w plikach .parque mog\u0119 nawet mie\u0107 transakcje ACID (jak u\u017cyj\u0119 formatu delta).<\/p>\n\n\n\n<p>W artykule nie b\u0119dziemy rozstrzyga\u0107, kiedy Snowflake jest lepszym wyborem. Chodzi o to, \u017ce <strong>Snowflake jest zbudowany dla In\u017cynier\u00f3w przez In\u017cynier\u00f3w<\/strong>. Dlatego ka\u017cdy do\u015bwiadczony programista b\u0119dzie nim zachwycony.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Taski i Task Graph<\/strong><\/h2>\n\n\n\n<p>Jednym z takich przyk\u0142adowych narz\u0119dzi jest funkcjonalno\u015b\u0107 Task\u00f3w i Task Graph, kt\u00f3ry jest w sumie implementacj\u0105 podej\u015bcia DAG (directed acyclic graph \u2013 skierowany graf acykliczny) w kontek\u015bcie potok\u00f3w danych.<\/p>\n\n\n\n<p>Czym wi\u0119c s\u0105 Taski i Task Graph? Zgodnie z dokumentacj\u0105:<\/p>\n\n\n\n<p>\u201eTaski to funkcje zdefiniowane przez u\u017cytkownika do automatyzacji i harmonogramowania procesu\u201d.<\/p>\n\n\n\n<p>Mog\u0105 uruchamia\u0107 nast\u0119puj\u0105ce elementy:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>pojedyncze zapytania SQL,<\/li>\n\n\n\n<li>procedury sk\u0142adowane,<\/li>\n\n\n\n<li>logik\u0119, u\u017cywaj\u0105c Snowflake Scripting.<\/li>\n<\/ul>\n\n\n\n<p>Taski mog\u0105 by\u0107 wyzwalane poprzez harmonogram lub poprzez strumienie (Streams) w tabelach, co daje dodatkow\u0105 mo\u017cliwo\u015b\u0107 budowania bardziej dynamicznych przep\u0142yw\u00f3w ETL.<\/p>\n\n\n\n<p>Task Graph jest u\u017cywany do powi\u0105zania wielu Task\u00f3w razem w jeden graf DAG w celu zarz\u0105dzania zale\u017cno\u015bciami. Ka\u017cdy Task Graph sk\u0142ada si\u0119 z Root Taska, kt\u00f3ry jest pocz\u0105tkiem sekwencji, oraz Task\u00f3w przypi\u0119tych do niego.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"641\" height=\"481\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/02\/image1-1.png\" alt=\"Task Graph sk\u0142adaj\u0105cy si\u0119 z Root Taska i Task\u00f3w przypi\u0119tych do niego\" class=\"wp-image-30351\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/02\/image1-1.png 641w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/02\/image1-1-300x225.png 300w\" sizes=\"(max-width: 641px) 100vw, 641px\" \/><figcaption class=\"wp-element-caption\">Ryc. 1 Task Graph sk\u0142adaj\u0105cy si\u0119 z Root Taska i Task\u00f3w przypi\u0119tych do niego<\/figcaption><\/figure>\n\n\n\n<p>Mo\u017cesz stworzy\u0107 wiele Task Graph\u00f3w dla r\u00f3\u017cnych cel\u00f3w, takich jak \u0142adowanie dzienne i miesi\u0119czne czy \u0142adowanie danych sprzeda\u017cowych lub magazynowych.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Root Task<\/strong><\/h2>\n\n\n\n<p>Jak ju\u017c wspomina\u0142em, Root Task mo\u017ce by\u0107 wyzwalany na wiele sposob\u00f3w:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>uruchamiany zgodnie z ustalonym harmonogramem,<\/li>\n\n\n\n<li>wyzwolony przez stream, tak by uruchomi\u0107 przetwarzanie w przypadku zmiany danych,<\/li>\n\n\n\n<li>uruchomiony r\u0119cznie.<\/li>\n<\/ul>\n\n\n\n<p>Aby stworzy\u0107 Root Taska, odwo\u0142amy si\u0119 do oficjalnej dokumentacji Snowflake \u2013\u00a0<a href=\"https:\/\/docs.snowflake.com\/en\/sql-reference\/sql\/create-task\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >CREATE TASK | Snowflake Documentation<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Create Root Task<\/strong><\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nCREATE OR REPLACE TASK SFPOCDB.SFPOC_TWITTER_DATA.ROOT_TASK -- Name of the TASK objects\n    WAREHOUSE = SFPOCWH -- Warehouse that would be used to run tasks \n    COMMENT = &#039;Place your comments&#039;\n    ALLOW_OVERLAPPING_EXECUTION = FALSE\n    AS\n        DECLARE\n\t-- declaring variables and its starting values\n            run_task_id text DEFAULT (SELECT SYSTEM$TASK_RUNTIME_INFO(&#039;CURRENT_TASK_GRAPH_RUN_GROUP_ID&#039;));\n            root_task_id text DEFAULT (SELECT SYSTEM$TASK_RUNTIME_INFO(&#039;CURRENT_ROOT_TASK_UUID&#039;));\n            status VARCHAR(30);\n            start_time     timestamp DEFAULT (SELECT CONVERT_TIMEZONE(&#039;UTC&#039;, &#039;Europe\/Vienna&#039;, CURRENT_TIMESTAMP()));\n            end_time       timestamp;\n        BEGIN\n            -- log starting new batch run\n            INSERT INTO SFPOCDB.SFPOC_TWITTER_DATA.BATCH_LOG\n                VALUES (:run_task_id, :root_task_id,&#039;START&#039;,:start_time,null);\n        END;\n<\/pre><\/div>\n\n\n<p>Root Task jest pocz\u0105tkiem przetwarzania. Zazwyczaj u\u017cywam go w celu stworzenia jakiego\u015b wst\u0119pnego logowania, na przyk\u0142ad o rozpocz\u0119ciu procesu ETL. Oczywi\u015bcie mo\u017cna u\u017cywa\u0107 tabeli TASK_HISTORY, kt\u00f3ra jest wbudowana w Snowflake, ale zauwa\u017cy\u0142em, \u017ce wpisy tam pojawiaj\u0105 si\u0119 z pewnym op\u00f3\u017anieniem.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nSELECT * FROM TABLE(SFPOCDB.INFORMATION_SCHEMA.TASK_HISTORY());\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\"><strong>W\u0142asna tabela do logowania<\/strong><\/h2>\n\n\n\n<p>Zdecydowa\u0142em wi\u0119c, \u017ce stworz\u0119 swoj\u0105 w\u0142asn\u0105 tabel\u0119 do logowania, aby mie\u0107 wi\u0119ksz\u0105 elastyczno\u015b\u0107 i zbiera\u0107 wszystkie informacje o stanie zada\u0144 tak szybko, jak to mo\u017cliwe<\/p>\n\n\n\n<p>W tym celu wykorzysta\u0142em funkcj\u0119 <strong><code>SYSTEM$TASK_RUNTIME_INFO<\/code><\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>SYSTEM$TASK_RUNTIME_INFO('CURRENT_TASK_GRAPH_RUN_GROUP_ID') <\/code>\u2013 UUID obecnego uruchomienia ETL<\/li>\n\n\n\n<li><code>SYSTEM$TASK_RUNTIME_INFO('CURRENT_ROOT_TASK_UUID')<\/code> \u2013 UUID identyfikuj\u0105cy ROOT TASK do kt\u00f3rego TASK jest podpi\u0119ty<\/li>\n<\/ul>\n\n\n\n<p>Wi\u0119cej informacji mo\u017cna znale\u017a\u0107 <a href=\"https:\/\/docs.snowflake.com\/en\/sql-reference\/functions\/system_task_runtime_info\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >w dokumentacji Snowflake<\/a>.<\/p>\n\n\n\n<p>Stw\u00f3rzmy kolejnego Taska w Task Graph, kt\u00f3ry jest zale\u017cny od Root Task. Nazwiemy go TASK_A.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Create TASK_A<\/strong><\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nCREATE OR REPLACE TASK SFPOCDB.SFPOC_TWITTER_DATA.TASK_A\n    WAREHOUSE = SFPOCWH\n    COMMENT = &#039;Task A in a Task Graph&#039;\n    AFTER SFPOCDB.SFPOC_TWITTER_DATA.ROOT_TASK --names of the tasks, that are predecessors of current task, separated with comma (,)\n    AS\n        DECLARE\n            run_task_id         text DEFAULT (SELECT SYSTEM$TASK_RUNTIME_INFO(&#039;CURRENT_TASK_GRAPH_RUN_GROUP_ID&#039;));\n            task_id             text DEFAULT (SELECT SYSTEM$TASK_RUNTIME_INFO(&#039;CURRENT_TASK_NAME&#039;));\n            query_id            text;\n            status              VARCHAR(30);\n            start_time          timestamp DEFAULT (SELECT CONVERT_TIMEZONE(&#039;UTC&#039;, &#039;Europe\/Vienna&#039;, CURRENT_TIMESTAMP()));\n            end_time            timestamp;\n            affected_records    int;\n            error_number        int;\n            error_message       text;\n        BEGIN\n            -- log procedure start\n            INSERT INTO DB_AT_DEV.STAGING.BATCHJOBRUNLOG\n                VALUES (:run_task_id, :task_id, null, &#039;START&#039;, :start_time, null, null, null, null );      \n \n            -- call the procedure\n            CALL procedure_schema.procedure_name();\n \n            -- log end\n            query_id := SQLID;\n            end_time := (SELECT CONVERT_TIMEZONE(&#039;UTC&#039;, &#039;Europe\/Vienna&#039;, CURRENT_TIMESTAMP()));\n            affected_records := sqlrowcount;\n            \n            -- log procedure finish success\n            \n            UPDATE DB_AT_DEV.STAGING.BATCHJOBRUNLOG\n                SET \n                    QUERY_ID = :query_id,\n                    STATUS = &#039;FINISHED&#039;,\n                    END_TIME = :end_time,\n                    AFFECTED_RECORDS = :affected_records\n                WHERE \n                    RUN_ID = :run_task_id\n                    AND TASK_ID = :task_id;\n                           \n            -- log procedure finish error\n        EXCEPTION\n            WHEN OTHER THEN\n                query_id := SQLID;\n                affected_records := sqlrowcount; \n                end_time := (SELECT CONVERT_TIMEZONE(&#039;UTC&#039;, &#039;Europe\/Vienna&#039;, CURRENT_TIMESTAMP()));\n \n                UPDATE DB_AT_DEV.STAGING.BATCHJOBRUNLOG\n                    SET \n                        QUERY_ID = :query_id,\n                        STATUS = &#039;FAILED&#039;,\n                        END_TIME = :end_time,\n                        AFFECTED_RECORDS = :affected_records,\n                        ERROR_NUMBER = 1,\n                        ERROR_MESSAGE = :sqlerrm\n                    WHERE \n                        RUN_ID = :run_task_id\n                        AND TASK_ID = :task_id;\n                           RAISE;               \n        END;\n<\/pre><\/div>\n\n\n<p>W tym Tasku opakowa\u0142em procedur\u0119 SQL, kt\u00f3ra wykonuje w\u0142a\u015bciwy ETL (polecenie <code>CALL procedure_schema.procedure_name();<\/code> ) dodatkow\u0105 logik\u0105, tak aby utrzymywa\u0107 logi dotycz\u0105ce Task\u00f3w w osobnej tabeli.<\/p>\n\n\n\n<p>U\u017cy\u0142em dodatkowo takich zmiennych jak:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>SYSTEM$TASK_RUNTIME_INFO('CURRENT_TASK_NAME')<\/code> \u2013 nazwa obecnego Taska<\/li>\n\n\n\n<li><code>SQLID<\/code> \u2013 UUID identyfikuj\u0105cy Root Task, do kt\u00f3rego Task jest podpi\u0119ty<\/li>\n\n\n\n<li><code>SQLROWCOUNT<\/code> \u2013 ID ostatniego uruchomionego zapytania<\/li>\n<\/ul>\n\n\n\n<p>Warto podkre\u015bli\u0107, \u017ce to by\u0142a <strong>specyfika mojego zadania<\/strong> \u2013 logowa\u0107 informacj\u0119 o statusie Taska do osobnej tabeli. Ale mo\u017cesz u\u017cy\u0107 innej struktury logowania Taska, dodaj\u0105c dodatkowe informacje lub logik\u0119 do przetwarzania ETL, wci\u0105\u017c utrzymuj\u0105c logik\u0119 biznesow\u0105 w osobnych procedurach. Mo\u017cesz nawet dokona\u0107 refactoringu i opakowa\u0107 logik\u0119 techniczn\u0105 w procedury lub funkcj\u0119.<\/p>\n\n\n\n<p>Takie podej\u015bcie pozwala na \u0142atwiejsze utrzymanie kodu w przysz\u0142o\u015bci. Odseparowanie technicznej i biznesowej cz\u0119\u015bci rozwi\u0105zania naprawd\u0119 oszcz\u0119dza czas podczas implementacji zmian i naprawiania b\u0142\u0119d\u00f3w.<\/p>\n\n\n\n<p>Ka\u017cdy z Task\u00f3w musi by\u0107 ustawiony w status RESUME, by zosta\u0142 uruchomiony.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nALTER TASK DB_AT_DEV.STAGING.LOAD_INTEGRATION_DIM_CUSTOMER_TASK RESUME;\n<\/pre><\/div>\n\n\n<p>Zaraz po stworzeniu lub zmianie w Tasku, ten jest standardowo ustawiany w stan SUSPEND, co oznacza, \u017ce jest wstrzymany.<\/p>\n\n\n\n<p>Mo\u017cesz tak\u017ce zmieni\u0107 status wszystkich zada\u0144 powi\u0105zanych z Root Task, u\u017cywaj\u0105c <strong><code>SYSTEM$TASK_DEPENDENTS_ENABLE<\/code><\/strong>\u00a0\u2013 wi\u0119cej <a href=\"https:\/\/docs.snowflake.com\/en\/sql-reference\/functions\/system_task_dependents_enable\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >w dokumentacji Snowflake<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Tworzenie logu po uruchomieniu ca\u0142ego potoku ETL<\/strong><\/h2>\n\n\n\n<p>Kolejn\u0105 rzecz\u0105, kt\u00f3r\u0105 chcieliby\u015bmy zrobi\u0107, jest stworzenie logu po uruchomieniu ca\u0142ego potoku ETL. W tym celu mo\u017cemy u\u017cy\u0107 innego typu zada\u0144 \u2013 Finalize Task. To specjalny rodzaj zada\u0144, kt\u00f3ry przy\u0142\u0105cza si\u0119 do Root Taska, ale uruchamia si\u0119 zawsze po zako\u0144czeniu wszystkich zada\u0144 w Task Graph (niezale\u017cnie od tego, czy zako\u0144cz\u0105 si\u0119 sukcesem, czy b\u0142\u0119dem).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Create Finalize Task<\/strong><\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nCREATE OR REPLACE TASK SFPOCDB.SFPOC_TWITTER_DATA.FINALIZE_TASK\n    WAREHOUSE = SFPOCWH\n    COMMENT = &#039;Finalize Task&#039;\n    FINALIZE = SFPOCDB.SFPOC_TWITTER_DATA.ROOT_TASK \u2013- indicates it is finalize task\n    AS\n        DECLARE\n            run_task_id text DEFAULT (SELECT SYSTEM$TASK_RUNTIME_INFO(&#039;CURRENT_TASK_GRAPH_RUN_GROUP_ID&#039;));\n            root_task_id text DEFAULT (SELECT SYSTEM$TASK_RUNTIME_INFO(&#039;CURRENT_ROOT_TASK_UUID&#039;));\n            status VARCHAR(30);\n            start_time     timestamp DEFAULT (SELECT CONVERT_TIMEZONE(&#039;UTC&#039;, &#039;Europe\/Vienna&#039;, CURRENT_TIMESTAMP()));\n            end_time       timestamp;\n            nb_of_failed   INT;\n        BEGIN\n            end_time := (SELECT CONVERT_TIMEZONE(&#039;UTC&#039;, &#039;Europe\/Vienna&#039;, CURRENT_TIMESTAMP()));\n            --log starting new batch run\n            -- check if there are no tasks finished with FAILED status\n            nb_of_failed := (SELECT COUNT(1) FROM DB_AT_DEV.STAGING.BATCHJOBRUNLOG WHERE STATUS = &#039;FAILED&#039; AND RUN_ID=:run_task_id);\n            status := (SELECT IFF(:nb_of_failed&gt;=1,&#039;FAILED&#039;,&#039;FINISHED&#039;));\n            -- update log\n            UPDATE DB_AT_DEV.STAGING.BATCHRUNLOG\n                SET \n                    STATUS = :status,\n                    END_TIME = :end_time\n                WHERE RUN_ID = :run_task_id AND ROOT_TASK_ID = :root_task_id\n                ;\n        END;\n<\/pre><\/div>\n\n\n<p>Zadania Finalize Task s\u0105 \u015bwietne, gdy musimy posprz\u0105ta\u0107 i zamkn\u0105\u0107 proces ETL, dlatego \u017ce zawsze uruchomi\u0105 si\u0119 jako ostatnie. Ja u\u017cywam ich do logowania czasu zako\u0144czenia przetwarzania i jego statusu.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Podgl\u0105danie potoku<\/strong><\/h2>\n\n\n\n<p>Mamy kilka mo\u017cliwo\u015bci podejrzenia naszego potoku.<\/p>\n\n\n\n<p>Pierwsza z nich to u\u017cycie metody Show Tasks:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nSHOW TASKS;\n<\/pre><\/div>\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img decoding=\"async\" width=\"1024\" height=\"485\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/02\/image2-1024x485.png\" alt=\"Podgl\u0105danie potoku \u2013 metoda Show Tasks\" class=\"wp-image-30353\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/02\/image2-1024x485.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/02\/image2-300x142.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/02\/image2-768x364.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/02\/image2-1536x728.png 1536w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/02\/image2.png 1914w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Ryc. 2 Podgl\u0105danie potoku \u2013 metoda Show Tasks<\/figcaption><\/figure>\n\n\n\n<p>Mo\u017ce by\u0107 u\u017cyteczna, ale do lepszego pogl\u0105du na wszystkie zadania lepszy jest wbudowany wizualizer Task Graph:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img decoding=\"async\" width=\"1024\" height=\"485\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/02\/image3-1024x485.png\" alt=\"Podgl\u0105danie potoku \u2013 wykorzystanie wbudowanego wizualizera Task Graph\" class=\"wp-image-30355\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/02\/image3-1024x485.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/02\/image3-300x142.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/02\/image3-768x364.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/02\/image3-1536x728.png 1536w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/02\/image3.png 1912w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Ryc. 3 Podgl\u0105danie potoku \u2013 wykorzystanie wbudowanego wizualizera Task Graph<\/figcaption><\/figure>\n\n\n\n<p>Tutaj mo\u017cecie sprawdzi\u0107 detale i definicj\u0119 zadania, ale r\u00f3wnie\u017c histori\u0119 uruchomie\u0144, status i inne parametry.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Uruchamianie zada\u0144<\/strong><\/h2>\n\n\n\n<p>Jak ju\u017c wspomnia\u0142em, zadania mog\u0105 by\u0107 uruchamiane wed\u0142ug zadanego harmonogramu (jest to definiowane podczas tworzenia lub zmiany Root Taska), wyzwalane przez strumienie danych (streams) lub uruchamiane r\u0119cznie. Mog\u0105 by\u0107 r\u00f3wnie\u017c konfigurowane w taki spos\u00f3b, by wiele instancji tego samego zadania przebiega\u0142o r\u00f3wnolegle.<\/p>\n\n\n\n<p>Aby uruchomi\u0107 zadanie r\u0119cznie, nale\u017cy u\u017cy\u0107 polecenia:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nEXECUTE TASK SFPOCDB.SFPOC_TWITTER_DATA.ROOT_TASK \n<\/pre><\/div>\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/oferty-pracy\/\" target=\"_blank\" rel=\"noreferrer noopener\"><img decoding=\"async\" width=\"737\" height=\"170\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/02\/praca-m-2.jpg\" alt=\"oferty pracy\" class=\"wp-image-30357\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/02\/praca-m-2.jpg 737w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/02\/praca-m-2-300x69.jpg 300w\" sizes=\"(max-width: 737px) 100vw, 737px\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Podsumowanie<\/strong><\/h2>\n\n\n\n<p>Jest te\u017c wiele innych powod\u00f3w, dla kt\u00f3rych uwa\u017cam Taski w Snowflake za \u015bwietne rozwi\u0105zanie do budowy proces\u00f3w ETL po stronie bazy danych. Dodatkowo, procedury sk\u0142adowane mog\u0105 by\u0107 pisane nie tylko w SQL, ale te\u017c w Javie, Javascript\u2019cie, Pythonie lub Scali.<\/p>\n\n\n\n<p>Je\u017celi chcia\u0142by\u015b dowiedzie\u0107 si\u0119 wi\u0119cej, sprawd\u017a dokumentacj\u0119 na\u00a0<a href=\"https:\/\/docs.snowflake.com\/en\/user-guide\/tasks-intro\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >Introduction to tasks | Snowflake Documentation<\/a>.<\/p>\n\n\n\n<p>***<\/p>\n\n\n\n<p>Je\u015bli interesuj\u0105 Ci\u0119 implementacje, przyk\u0142ady i fragmenty kodu, zajrzyj r\u00f3wnie\u017c <a href=\"https:\/\/sii.pl\/blog\/development-na-twardo\/\" target=\"_blank\" rel=\"noopener\" title=\"\">do innych artyku\u0142\u00f3w z kategorii development na twardo. <\/a><\/p>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;30350&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;8&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;4.9&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;11&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;4.9\\\/5 ( votes: 8)&quot;,&quot;size&quot;:&quot;18&quot;,&quot;title&quot;:&quot;Orkiestracja za pomoc\u0105 Snowflake Tasks&quot;,&quot;width&quot;:&quot;136.6&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} ( {votes}: {count})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 136.6px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 14.4px;\">\n            4.9\/5 ( votes: 8)    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>Im d\u0142u\u017cej pracuj\u0119 ze Snowflake, tym bardziej si\u0119 w nim zakochuj\u0119. Na pocz\u0105tku my\u015bla\u0142em, \u017ce to tylko nast\u0119pna us\u0142uga hurtowni &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.pl\/blog\/orkiestracja-za-pomoca-snowflake-tasks\/\">Continued<\/a><\/p>\n","protected":false},"author":698,"featured_media":30359,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1314],"tags":[2794,2792,2791,1546,1512],"class_list":["post-30350","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development-na-twardo","tag-da","tag-orkiestracja","tag-snowflake","tag-przeglad-narzedzi","tag-poradnik"],"acf":[],"aioseo_notices":[],"republish_history":[],"featured_media_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/02\/Orkiestracja-za-pomoca-Snowflake-TASKS.jpg","category_names":["Development na twardo"],"_links":{"self":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/30350"}],"collection":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/users\/698"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/comments?post=30350"}],"version-history":[{"count":1,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/30350\/revisions"}],"predecessor-version":[{"id":30361,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/30350\/revisions\/30361"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media\/30359"}],"wp:attachment":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media?parent=30350"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/categories?post=30350"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/tags?post=30350"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}