😫

redashからSnowflakeを参照したらクレジット消費が異常に増えたお話

2022/04/20に公開約3,200字2件のコメント

前置き

はじめまして。株式会社GENDAのこみぃです。

株式会社GENDAではデータウェアハウスとしてSnowflake、BIツールとしてredashを使っています。
この設計は初期段階から決めており、Snowflakeのトライアル期間にはまずはこの部分を構築しました。

さて、Snowflakeにデータを転送し、redashで接続設定をし、数日経ってふとクレジット消費量を確認すると、そこには異常に消費されたクレジットの姿が!!

幸いにして本運用になる前に修正することができましたが、これ以上同じ悲しみを背負う人が出ないように、SnowflakeとBIツールをつなぐ際に気をつけるべき設定についてまとめました。

Snowflakeの料金体系

Snowflakeの料金体系は以下の2つになっています

  • データ量に応じたストレージの料金
  • コンピュータリソースの利用料金(クレジットという概念で計算される)

基本的に料金の大部分を占めるのは後者なので、コンピュータリソースの利用を抑えていくのが費用を抑えるコツになっていきます。

ここで注意したいのが、以下の点です。

  • コンピュータリソースは稼働させた時間に対しての従量課金である
  • コンピュータリソースはクエリを打ったりすると起動され、設定された時間(デフォルト10分)以上処理が行われない場合に自動停止される。

これがどういうことかというと、 利用する時間帯が決まっていてその間に色々なクエリを打つ運用であれば直感的なクレジット消費量になるけれど、定期的にクエリを打つような運用だと思った以上にクレジット消費量が多くなる ということです。

これにより何が起こるかは、後述していきます。

何が起きていたか

今回なぜクレジット消費量が激増していたか、理由は2つありました。順番に解説します。

redashからsnowflakeへ定期的なテーブルスキーマ参照があった

redashはクエリ作成画面にて、選択しているデータソースのテーブルスキーマの一覧を表示してくれる便利な機能があります。

非常に便利な機能ですが、こいつが曲者です。
このテーブルスキーマを表示するため、redashは定期的にデータソースに対して以下のようなクエリを発行しています。

schema_select
SELECT col.table_schema,
               col.table_name,
               col.column_name
        FROM {db_name}.information_schema.columns col
        WHERE col.table_schema <> 'INFORMATION_SCHEMA'

この参照クエリの間隔はデフォルト設定ではなんと30分。

デフォルトで利用していると30分に一回snowflakeのcomputeが呼び出されて起動されることになります。結果的にクレジット消費はえらいことになります。

幸いにしてこの間隔はredashのオプションをいじることで変更が可能です。

https://redash.io/help/open-source/admin-guide/env-vars-settings

REDASH_SCHEMAS_REFRESH_SCHEDULE がそれにあたりますので、1440(min)などの長い時間を指定することで余計な処理が走らないようにしましょう。

ちなみに自動更新しなくてもテーブルを追加したときには手動で更新すれば済む話です。

redashだけではなくmetabaseなどにも同じような機能がありますので、BIツールを使う場合にはそういう仕様がないか確認するのが良いでしょう。

redash側でクエリをキャンセルしてもSnowflake側ではクエリの処理が続いていた

redashをつかっていると以下のようなことがよくあると思います。

「クエリなかなか終わらないな。あ、よく見たらここjoin間違ってた。あぶない」
ポチっと(キャンセルを押す音)
「よし。クエリを直してと。改めてExecute。おお。2秒で返ってきたわ。神か。」

一見何も問題がないように思われますが、これが非常に危険です。
というのも、redashのボタンでクエリをキャンセルしてもsnowflake側では処理が続いている場合があります。

特にクエリ自体に問題がある場合にはComputeリソースを食い、場合によってはsnowflake側で設定しているタイムアウトまでクエリが続くことになります。

snowflakeのデフォルトのタイムアウトはなんと 3 2日。
最悪の場合には computeのサイズ x 24時間 x 3 2日 ものクレジットが消費されることになります(1敗)。~~

※2022/06/16追記
※↑ご指摘いただいたのですが、デフォルトは2日でした。失礼しました。

こちらはsnowflakeの設定でタイムアウトを設定することで回避できます。
computeごとに以下のように設定を変えておくのがいいでしょう。

alter_compute
alter warehouse {compute_warehouse_name} set STATEMENT_TIMEOUT_IN_SECONDS=300;

One more thing

自動でCOMPUTEを停止する時間は短くしておきましょう

さて、最初にお話した内容を思い出してみましょう。

後者でさらっと「デフォルトは10分」と書いてありますね。こちらは10分(600秒)も要らないので、短くしておきましょう。

alter_compute
alter warehouse {compute_warehouse_name} set AUTO_SUSPEND=120;

データ基盤は金食い虫扱いされがちですので、こういうところでしっかり費用を抑えていきたいですね。
※ちなみに120秒にしているのは徐々に短くして試していっているからで、そのうち60秒にしそうな気がします。

むすび

今回の2つの設定を導入したところ、異常に消費されていたクレジットは正常に戻り、今では非常に安くSnowflakeを利用できています。

もし事前の見積もりよりもクレジットの消費量が多いと思ったら今回の設定や、その他にも定期的な何かが動いてないかを確認するのが良いと思います。

さらに詳細が聞きたいという方は、私がわかる範囲であればお答えしますので、Twitterあたりでお気軽にお声がけください。
@kommy_jp

本日はこのあたりで。
それじゃあ、バイバイ!

Discussion

ブログを書いて頂きましてありがとうございます!
1点だけ誤記と思われる箇所があるのでコメントさせて下さい。STATEMENT_TIMEOUT_IN_SECONDSのデフォルトは172800秒(2日)となります。

https://docs.snowflake.com/ja/sql-reference/parameters.html#statement-timeout-in-seconds
また、参考までにですが、ABORT_DETACHED_QUERYをtrueにすることを検討頂いても良いかもしれません。
https://docs.snowflake.com/ja/sql-reference/parameters.html#abort-detached-query

コメントありがとうございます。
パラメータのデフォルト値については理解が浅くてすみませんでした。追記をいれておきます。
ABORT_DETACHED_QUERYもありがとうございます。こういうTipsを指摘していただけるのは非常にありがたいです。

ログインするとコメントできます