Snowflakeのサーバーレスタスクを試してみた #SnowflakeDB

2021.12.11

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

※本エントリは、Snowflakeをより使いこなそう! Advent Calendar 2021の11日目の記事となります。

さがらです。

Snowflakeの新機能、サーバーレスタスクを試してみたので、本記事でまとめます。 ※サーバーレスタスクは2021年12月11日時点でプレビュー機能のため、ご注意ください。

※2022年9月28日追記:本機能は、2022年9月22~23日頃にリリースされたVersion6.31にて、GAとなりました!積極的に使っていきましょう!!

タスクとは

まず、Snowflakeのタスクについて振り返ります。

タスクは、任意のSQLについて定期的なスケジュールを組んで実行できる機能です。

データ分析基盤において、定期的にSQLを実行して分析に使用するテーブルを更新するバッチ処理はほぼ必須の機能です。このバッチ処理に当たることをタスクで実現できます。

また、対象のテーブルの変更データを保持するストリームと合わせることで、新しいデータの更新があったらタスクを実行するという処理も実現可能です。

タスク、及びタスクとストリームの組み合わせについては弊社でも記事を書いておりますので、ぜひ併せて御覧ください。

サーバーレスタスクとは

一方で、通常のタスクは設定時にウェアハウスを設定しなければ使えません。

SnowflakeのウェアハウスもGUIで簡単に定義ができるのですが、タスクにウェアハウスを設定しないといけないため、以下の問題が発生します。

  • タスク設定しているウェアハウスのサイズで何が最適かわからない。状況によっては何度かサイズを変えてタスクのSQLを実行し最適なサイズを選定しないといけない。
  • どんなに短い時間で終わるタスクであっても、対象のウェアハウスに対して最低60秒分のクレジット消費が発生する。

こんな時に、今回の新機能であるサーバーレスタスクが役に立ちます!特徴としては、以下の2点が挙げられます。

  • ウェアハウスの設定が不要。オプションでタスクのサイズの設定は可能(しかしこのオプションの値に関係なく、タスクを数回実行後Snowflake側で最適なサイズに設定してくれます)
  • クレジット消費は基本的にタスクが実行されている分だけ行われる。詳細はこちらの公式Docが参考になると思います。

試してみた

ということで、Snowflakeのサーバーレスタスクを試してみたいと思います。

前準備

キャッシュの無効化

まず、クエリ結果キャッシュを活用しないように以下のクエリを実行して無効化します。

use role accountadmin;
alter account set use_cached_result = false;

タスク用データの準備

SnowflakeのサンプルデータであるSNOWFLAKE_SAMPLE_DATAのうち、TPCH_SF1スキーマのCUSTOMERテーブルを使用します。 このテーブルは、15万件のデータです。

SNOWFLAKE_SAMPLE_DATA上のテーブルを用いたタスクは定義できないため、以下のクエリを実行し、my_customerとして別テーブルで定義します。

use role sysadmin;
create or replace database tasktest_db;

use database tasktest_db;
use schema public;
create or replace table my_customer as
    select * from "SNOWFLAKE_SAMPLE_DATA"."TPCH_SF1"."CUSTOMER";

タスクに設定するクエリの確認

前述のクエリで作成した15万件のデータを持つテーブルmy_customerに対して、全件取得するクエリを記述してその内容を新しくmy_customer_2として定義するクエリをサーバーレスタスクに設定します。

create or replace table my_customer_2 as
    select * from my_customer;

実際にサイズXSのウェアハウスで動かすと、1.76秒かかりました。XSでも充分な速度が出ているクエリになります。

サーバーレスタスクの定義

前述の準備を行った上で、サーバーレスタスクを以下のクエリで定義します。

use role accountadmin; -- 今回は検証のため、ACCOUNTADMINで実施します。実運用ではTASKADMINのようなロールを作ることが望ましいです。
create or replace task serverlesstest
    schedule = '1 minute'
    user_task_managed_initial_warehouse_size = 'LARGE'
    as
    create or replace table my_customer_2 as
    select * from my_customer;

alter task serverlesstest resume; -- タスクの有効化

ポイントは、user_task_managed_initial_warehouse_sizeというウェアハウスの初期サイズのオプションを、あえてLARGEに設定しているところです。 この状態で、一定回数タスクを実行し、使用するウェアハウスや消費クレジットに変化があるかを見てみます。

検証結果

上述のクエリを実行して、このサーバーレスタスクを10回実行させてどうなったかを確認してみます。(確認にACCOUNT_USAGEを使用していますが、こちらのスキーマは結果の反映に時間がかかりますので、もし皆様が試される場合はご注意ください。)

TASK_HISTORYの確認

まず、ACCOUNT_USAGETASK_HISTORYを確認してみます。下図の通り、10回分SUCCEEDEDの履歴があることがわかると思います。

select * from "SNOWFLAKE"."ACCOUNT_USAGE"."TASK_HISTORY" order by scheduled_time desc;

QUERY_HISTORYの確認

この上で、使用するウェアハウスのサイズに変化があったかを確認してみます。 ACCOUNT_USAGEQUERY_HISTORYに対して、EXISTS句を使って上述のクエリの結果に関係するレコードだけを持ってくるように設定した、以下のクエリを実行してみます。

select -- カラム数が多いため一部のカラムのみ出力
    query_id,
    warehouse_name,
    warehouse_size,
    warehouse_type,
    start_time
from "SNOWFLAKE"."ACCOUNT_USAGE"."QUERY_HISTORY" quehis
where exists
(
    select * from "SNOWFLAKE"."ACCOUNT_USAGE"."TASK_HISTORY" tashis
    where quehis.query_id = tashis.query_id
        and tashis.task_schema_id = 22 -- 余計なタスクに関するレコードを出力しないようにするため
)
order by start_time desc;

すると、タスクを実行するごとにウェアハウスのサイズが小さくなり、最終的にはX-SMALLで実行されていることがわかりました。

より具体的には、このような結果を得られました。

  • LARGEで実行されたのは最初の1回だけ
  • 2回目はMEDIUM、3回目はSMALL、4回目以降はX-SMALL、と1つ1つサイズを変更して最適化されている

今回はあからさまに大きなウェアハウスを使用してみましたが、4回のタスク実行だけで最適化されるのは素晴らしいですね!!

SERVERLESS_TASK_HISTORYの確認

続いて、SERVERLESS_TASK_HISTORYという、サーバーレスタスクでの消費クレジット量を確認できるビューを見てみます。

select * from "SNOWFLAKE"."ACCOUNT_USAGE"."SERVERLESS_TASK_HISTORY"
where schema_id = 22; -- 余計なタスクに関するレコードを出力しないようにするため

こちらのクエリを実行すると、このタスクを10回実行するのに0.004175412クレジット消費していることがわかりました。

もし、これを普通のタスクで実行しようとすると、サイズXSのウェアハウスで10回実行した場合、対象のウェアハウスが10分間起動することになります。そのため、計算式は以下のようになり、0.166666666クレジット消費することになります。

  • XSのウェアハウスを1時間(60分)起動した場合の消費クレジット:1
  • 1/(10/60) = 0.166666666 クレジット

つまり、普通のタスクに比べて、約40分の1のクレジット節約が出来ているということがわかりました!

なぜここまでコストが節約出来ているのかというと、「サーバーレスタスクはコア単位、かつ秒単位の課金」であるためです。一方で通常のウェアハウスは、「ウェアハウス単位、最低1分の秒単位課金」です。そのため使用するコンピューティングリソースの面でも課金対象時間の面でも、サーバーレスタスクの方がより細かく管理されてクレジット消費の節約に繋がっているのです。

サーバーレスタスクでは最初の3回はSMALL~LARGEのサイズで動かしていたので、サーバーレスタスクに不利な条件にもかかわらず、このクレジット節約効果は素晴らしいと思います。

まとめ

サーバーレスタスクについてまとめてみました。

まだプレビュー機能ではありますが、普通のタスクと比べて、ウェアハウスの管理が必要なくクレジット消費もタスクが実行されている間だけ、と良いことばかりの機能です。 特に秒単位で終わってしまうようなタスクに関しては、サーバーレスタスクを用いることで消費クレジットをかなり抑えることが出来るのではないでしょうか。

また、Snowpipeもサーバーレスタスクと類似した使った分だけ課金される体系ですので、継続的にロードしたいファイルがストレージに溜まっていくのであれば、「COPYコマンドによるバルクロード×通常のタスク」よりも「Snowpipe×サーバーレスタスク」の方がコストを節約出来る可能性が高いと思います。

個人的な余談ですが、いつか普通のウェアハウスに関してもサイズを自動でスケールアップ・ダウンしてくれる機能が来ることを望んでいます。笑

次回

Snowflakeをより使いこなそう! Advent Calendar 2021、次回の12日目では、「ACCOUNTADMINを2人用意してPW紛失時の対応をシミュレートしてみた」というタイトルで執筆します。お楽しみに!