はじめに
本記事では、SnowflakeのWarehouseをより効率的に活用するためのWarehouseのMAX_CONCURRENCY_LEVELパラメータの設定について記述します。具体的には、Warehouseの基本的な概要から、クエリ処理の時間を短縮するためのパラメータ調整、さらにはTerraformを用いた設定方法等を解説します。
Snowflake Warehouseの概要
SnowflakeにおけるDML操作にはWarehouseが必要です。Warehouseは、クエリの実行に必要なリソースを提供するためのコンピューティングリソースです。
Warehouseにはサイズがあり、それに応じてリソースが割り当てられます。Warehouseのサイズは、X-Small、Small、Medium、Large、X-Large、2X-Large、3X-Large、4X-Large、5X-Large、6X-Largeがあります。(5X-Large、6X-Largeは基本的に使うことはありません。)
Snowflakeはクレジットという単位で課金されます。Warehouseのサイズが大きいほど、クレジットの消費が大きくなります。
以下は、Warehouseのサイズによるクレジットの消費量の一例です。
実行時間 | クレジット(XS) | クレジット(XL) | クレジット(5XL) |
0~60秒間 | 0.017 | 0.267 | 4.268 |
61秒間 | 0.017 | 0.271 | 4.336 |
2分間 | 0.033 | 0.533 | 8.532 |
10分間 | 0.167 | 2.667 | 42.668 |
1時間 | 1.000 | 16.000 | 256.000 |
Warehouseは1秒あたりの実行時間によって課金されますが、最低実行時間は60秒です。つまり、クエリが60秒未満で終了した場合でも、60秒分のクレジットが消費されます。
データのロード処理についてですが、Warehouseのサイズを大きくしてもデータのロード速度が必ずしも向上するわけではありません。
読み込まれるファイルの数やファイルのサイズによる影響の方が大きいことが多いです。
公式ドキュメントにも、大量のファイルを同時に一括でロードする場合でなければ、クレジット消費やパフォーマンスの観点からより小さいサイズのWarehouseで十分だと記載されています。※2
一方で、クエリ処理についてですが、特に複雑なクエリの場合には、Warehouseのサイズを大きくすることでクエリ処理の時間が短くなることがあります。Warehouseのサイズが大きくなると、クエリ処理に使うことができるコンピューティングリソースが増えるためです。
MAX_CONCURRENCY_LEVELパラメーター
一般的に、より複雑なクエリの実行時間を短くするために、Warehouseのサイズを大きくすることが有効ですが、それに伴いクレジットの消費も大きくなってしまいます。
そこで、MAX_CONCURRENCY_LEVELパラメーターを調整することで、Warehouseのサイズを変更することなく、クエリ処理の実行時間を短縮させることができる可能性があります。
MAX_CONCURRENCY_LEVELパラメーターは、以下のようなものです。
- Warehouseにおいて同時実行可能なクエリの数を制限するためのパラメーターです。
- この値に達した際に、シングルクラスターの場合、クエリのステートメントは、すでに割り当てられているリソースが解放されるか追加のリソースがプロビジョニングされるまで、キューに入ります。マルチクラスター(自動スケールモード)の場合は、新たなクラスターが追加されます。
- 厳密な制限ではなく、クエリがよりシンプルなものの場合は、この値を超えても実行されることがあります。クエリがより複雑なものの場合は、この値に達していなくてもキューに入ることがあります。
- デフォルト値は8です。
このパラメーターをデフォルトの8より小さい値にすることで、同時に実行できるクエリの数を制限することができます。
そうすると、各クエリに割り当てられるコンピューティングリソースが増えるため、Warehouseのサイズを大きくすることなく、クエリ処理時間を短縮することができる可能性があります。
Terraformでの設定
TerraformでMAX_CONCURRENCY_LEVELパラメーターを設定する方法について説明します。
以下のように、Terraformのsnowflake_warehouseリソースにMAX_CONCURRENCY_LEVELパラメーターを設定することができます。
WarehouseのサイズはX-Small、MAX_CONCURRENCY_LEVELは2としています。
resource "snowflake_warehouse" "testwh" {
name = "testwh"
comment = "test wh"
warehouse_size = "XSMALL"
max_concurrency_level = 2
}
terraform apply
を実行すると、Warehouseが作成されます。
SHOW PARAMETERS IN WAREHOUSE <warehouse_name>;
というクエリを実行することで、Warehouseのパラメーターを確認することができます。
今回は、SHOW PARAMETERS IN WAREHOUSE testwh;
を実行することで、以下のように出力されました。
STATEMENT_QUEUED_TIMEOUT_IN_SECONDSパラメーターとの組み合わせ
MAX_CONCURRENCY_LEVELパラメーターを設定することで、同時に実行できるクエリの数を制限することができますが、同時実行数を小さくした場合、クエリステートメントがキューに入り、実行待ちになってしまう可能性が高くなります。
試しに、上記で作成したWarehouseで以下のような、処理に時間がかかるクエリを3つ同時に実行してみます。
WITH RECURSIVE t(n) AS (
SELECT 1
UNION ALL
SELECT n+1 FROM t WHERE n < 10000000
)
SELECT COUNT(*) FROM t;
このクエリは、再帰的に1から10000000までの整数を生成し、その総数をカウントするものです。
そうすると以下のように実行中のままになります。
このような場合に、キューに入ったクエリを意図的にタイムアウトするように設定したいです。
STATEMENT_QUEUED_TIMEOUT_IN_SECONDSパラメーターをMAX_CONCURRENCY_LEVELと組み合わせると、キューに入っているクエリステートメントがタイムアウトするまでの時間を設定でき、未処理のキューが溜まり続けることを防ぐことができます。
STATEMENT_QUEUED_TIMEOUT_IN_SECONDSパラメーターは、以下のようなものです。
- SQLステートメントがキューに入っている時間(秒単位)を制限するためのパラメーターです。
- 個々のWarehouseに設定できます。
- このパラメータよりセッションタイムアウトが優先されます。
- デフォルト値は0です。0が設定されている場合は、タイムアウトが無効になります。
このパラメーターを0ではない値に設定することで、キューに入っているクエリステートメントがタイムアウトするまでの時間を設定することができます。
以下のようにこのパラメータを5で設定して、再び`terraform apply`を実行します。
resource "snowflake_warehouse" "testwh" {
name = "testwh"
comment = "test wh"
warehouse_size = "XSMALL"
max_concurrency_level = 2
statement_queued_timeout_in_seconds = 5
}
そして再び、`SHOW PARAMETERS IN WAREHOUSE testwh;`
を実行することで、以下のように出力されました。
再び前述したようなクエリを実行すると、以下のようにキューに入ったクエリがタイムアウトしました。
まとめ
- MAX_CONCURRENCY_LEVELパラメーターを設定することで、同時に実行できるクエリの数を制限することができます。
- 同時実行数を少なくすることで、各クエリに割り当てられるコンピューティングリソースが増えるため、Warehouseのサイズを大きくしなくても、クエリ処理の時間を短縮することができる可能性があります。
- STATEMENT_QUEUED_TIMEOUT_IN_SECONDSパラメーターを組み合わせることで、キューに入っているクエリステートメントがタイムアウトするまでの時間を設定することができます。
参考文献
- https://docs.snowflake.com/en/user-guide/warehouses-overview
- https://docs.snowflake.com/en/user-guide/performance-query-warehouse-max-concurrency
- https://docs.snowflake.com/en/sql-reference/sql/show-parameters
- https://docs.snowflake.com/en/sql-reference/parameters
- https://www.linkedin.com/pulse/snowflake-concurrency-parallel-processing-subhrajit-bandyopadhyay
※1 https://docs.snowflake.com/en/user-guide/warehouses-overview#impact-on-credit-usage-and-billing より引用
※2 https://docs.snowflake.com/en/user-guide/warehouses-overview#impact-on-data-loadingに記載あり