指定したウェアハウスでリソースが足りない時に一時的にリソースを増強してくれる「Query Acceleration」を試してみた #SnowflakeDB

2022.12.16

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

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

さがらです。

Snowflakeで、指定したウェアハウスでリソースが足りない時に一時的にリソースを増強してくれる「Query Acceleration」を試してみたので、その内容をまとめてみます。

※記事執筆時点(2022年12月7日)では、本機能はプレビュー機能ですのでご注意ください。

Query Accelerationとは

Query AccelerationはSnowflakeのウェアハウスに対して行う設定で、有効化していると、通常のクエリよりも多くのリソースを使用する外れ値に該当するクエリが発行された時に一時的にリソースを増強し、対象の外れ値クエリに対するパフォーマンスを向上できる機能となっております。

特に、BIツールのように非定型に自由に発行されるクエリを処理するウェアハウスにおいてメリットを受ける可能性が高い機能です。

より詳細な仕様については、公式Docも併せてご確認ください。

試してみた

それでは、実際にQuery Accelerationがどんな機能か試してみます!

前提

今回、以下のSnowflakeサンプルデータであるSNOWFLAKE_SAMPLPE_DATAデータベースのTPCDS_SF10TCLというスキーマにあるテーブルに対して、サイズXSのシングルクラスタのウェアハウスで以下のクエリを実行してみてみました。(このクエリは、こちらの海外での検証記事からの引用です。)

かかった時間は「4分49秒」でした。正直、時間がかかりすぎていますよね。このクエリに対して、Query Accelerationが適用できるか検証してみます。

 select  
    d.d_year as "Year",
    i.i_brand_id as "Brand ID",
    i.i_brand as "Brand",
    sum(ss_net_profit) as "Profit"
from   
    snowflake_sample_data.tpcds_sf10tcl.date_dim d 
    ,snowflake_sample_data.tpcds_sf10tcl.store_sales s
    ,snowflake_sample_data.tpcds_sf10tcl.item i
where 
   d.d_date_sk = s.ss_sold_date_sk
   and s.ss_item_sk = i.i_item_sk
   and i.i_manufact_id = 939
   and d.d_moy = 12
group by 
    d.d_year,
    i.i_brand,
    i.i_brand_id
order by 1, 4, 2
limit 200;

Query Accelerationが適用可能かどうかの判断

まず前述のクエリを実行した際のクエリIDを用いて、SYSTEM$ESTIMATE_QUERY_ACCELERATION関数を実行して、このクエリに対してQuery Accelerationが適用可能かどうかを確かめてみます。

PARSE_JSON関数と併せることで、VARIANT型の値として返す事ができます。

select parse_json(system$estimate_query_acceleration('01a8cc45-0000-a2c8-0000-95810001903e'));

上記のクエリを実行することで、下図の様に結果が返ってきます。注目すべきはstatusestimatedQueryTimesです。

statuseligibleの場合、対象のクエリはQuery Accelerationが適用可能であることを示しています。

estimatedQueryTimesでは、Query Accelerationの設定値であるスケールファクターをどの値にすることで、どのくらいの秒数でこのクエリの結果が返ってくることを見込めるかがわかります。

また、ACCOUNT_USAGEスキーマのQUERY_ACCELERATION_ELIGIBLEビューを用いても、Query Accelerationが適用可能なクエリを確認可能です。こちらのビューはデータ更新までにラグがありますが、運用時には定期的にこのビューを監視するのが良さそうですね。

以下は、QUERY_ACCELERATION_ELIGIBLEビューに対するクエリサンプルです。

use role accountadmin;
select query_id, eligible_query_acceleration_time
from snowflake.account_usage.query_acceleration_eligible
order by eligible_query_acceleration_time desc;

対象のウェアハウスでQuery Accelerationを有効化

では続いて、対象のウェアハウスでQuery Accelerationを有効化し、クエリの実行速度を確かめてみます!

まず、対象のウェアハウスでのQuery Accelerationの有効化方法ですが、SnowsightのGUIでも、SQLでも、変更可能です。

SnowsightからQuery Accelerationを有効化

対象のウェアハウスの設定画面から、クエリアクセラレーションを有効化し、スケール係数を任意の値に設定すればOKです。

SQLで有効化

alter warehouseコマンドで対象のウェアハウスに対し、enable_query_acceleration = trueにし、query_acceleration_max_scale_factorは任意の値を設定して、このコマンドを実行すればOKです。

alter warehouse <ウェアハウス名> set
  enable_query_acceleration = true
  query_acceleration_max_scale_factor = 8;

Query Accelerationの有効化した後の実行速度検証

次に、Query Accelerationの有効化した後にどのようにクエリ実行速度が改善されるかを見てみます。

さきほどSYSTEM$ESTIMATE_QUERY_ACCELERATION関数を実行した際は、下図のような結果でしたので、スケールファクターはコスパが良さそうな「4」と最大値である「17」で試してみます。

また、キャッシュの影響がないように、このセッションでのキャッシュを無効化しておきます。

alter session set use_cached_result = false;

Query Accelerationを有効化していない場合

こちらは参考値として、Query Accelerationを有効化していない場合のクエリプロファイルも見ておきます。TableScanが99.0%ということで、明らかにテーブルスキャンに時間がかかっていましたね。

スケールファクター「4」での検証

まず、下記のクエリを実行してQuery Accelerationを有効化します。スケールファクターに該当するquery_acceleration_max_scale_factorは「4」に設定します。

alter warehouse acceleration_test_wh set
  enable_query_acceleration = true
  query_acceleration_max_scale_factor = 4;

この上で、対象のクエリを実行すると「40秒」で結果が返ってきました。SYSTEM$ESTIMATE_QUERY_ACCELERATION関数では「67秒」という予測でしたが、この予測値よりも非常に早く結果が返ってきましたね。

クエリプロファイルを見ると、一番時間がかかっていたTableScanの実行時間の比率が少し下がっていることがわかります。

また、注目していただきたいのは「統計」欄のPartitions scanned by serviceScans selected for accelerationです。

Partitions scanned by serviceはQuery Accelerationによってスケールしたリソースによってスキャンされたマイクロパーティションの数を意味しており、Scans selected for accelerationはQuery Accelerationによってスキャンが高速化されたテーブル数を意味しています。

結果を見ると、Partitions scanned by serviceは「44987」、Scans selected for accelerationは「1」ということで、Query Accelerationが活きているのがわかりますね!

スケールファクター「17」での検証

まず、下記のクエリを実行してQuery Accelerationを有効化します。スケールファクターに該当するquery_acceleration_max_scale_factorは「17」に設定します。

alter warehouse acceleration_test_wh set
  enable_query_acceleration = true
  query_acceleration_max_scale_factor = 17;

この上で、対象のクエリを実行すると「32秒」で結果が返ってきました。SYSTEM$ESTIMATE_QUERY_ACCELERATION関数では「26秒」という予測でしたが、この予測値よりも遅く結果が返ってきました。

クエリプロファイルを見ると、スケールファクター「4」の時と比べても、各プロセスの実行時間の比率にそこまで変化があるようには見えませんでした。

「統計」欄を見ると、Partitions scanned by serviceは「45887」、Scans selected for accelerationは「1」ということで、スケールファクター「4」の時と比べると少しだけ上がっていますね!これが、スケールファクター「4」の時と比べて、実行時間が8秒ほど早くなったことにもつながっているのだと思います。

Query Accelerationのコストについて

Query Accelerationのコストですが、使用したリソース分、秒単位で支払う課金体系となっております。スケールしたリソース1つに付き1時間1クレジット、サービス利用として1時間1クレジット、それぞれかかるようです。

また、コストの確認方法ですがGUIの管理画面からも確認可能ですし、SQLからでも確認可能です。

以下では、SQLを用いた場合の確認方法について記しておきます。

ACCOUNT_USAGEのQUERY_ACCELERATION_HISTORYビュー

select
    warehouse_name,
    sum(credits_used) as total_credits_used
from snowflake.account_usage.query_acceleration_history
where start_time >= date_trunc(month, current_date)
group by 1
order by 2 desc;

INFORMATION_SCHEMAのQUERY_ACCELERATION_HISTORY関数

select * from
table(information_schema.query_acceleration_history(
  date_range_start=>dateadd(h, -12, current_timestamp)));

本機能の注意点

私も試してみた上での注意点としては、対象のウェアハウスで時間がかかるクエリ全てにQuery Accelerationが対応する訳ではありません。

例えば、Snowsightに最初からあるワークシート上のサンプルデータに対する下記のクエリを、サイズMEDIUMのシングルクラスタのウェアハウスで実行したところ、2分44秒かかりましたがSYSTEM$ESTIMATE_QUERY_ACCELERATION関数を実行しても、Query Accelerationの対象とならない"status": "ineligible"と返ってきてしまいました。

select /* { "query":"query96","streamId":0,"querySequence":1 } */  count(*)
from store_sales
    ,household_demographics
    ,time_dim, store
where ss_sold_time_sk = time_dim.t_time_sk
    and ss_hdemo_sk = household_demographics.hd_demo_sk
    and ss_store_sk = s_store_sk
    and time_dim.t_hour = 8
    and time_dim.t_minute >= 30
    and household_demographics.hd_dep_count = 6
    and store.s_store_name = 'ese'
order by count(*)
limit 100;

Query Acceleration機能の前提としては、基本的には通常のウェアハウスで運用していただき、もしパフォーマンスが出ていないクエリがあった場合には、前述のSYSTEM$ESTIMATE_QUERY_ACCELERATION関数や、ACCOUNT_USAGEスキーマのQUERY_ACCELERATION_ELIGIBLEビューを用いて、Query Accelerationが有効かを確認しその上でQuery Accelerationを有効化する、というプロセスが必要だと思います。

クラスタリングの設定やクエリの書き方1つでもパフォーマンスがだいぶ変わる可能性もありますので、Query Accelerationやウェアハウスのサイズアップに頼りすぎないように、注意しましょう!

最後に

Snowflakeで、指定したウェアハウスでリソースが足りない時に一時的にリソースを増強してくれる「Query Acceleration」を試してみました。

クラスタリングの設定やクエリの内容を見直しても十分にパフォーマンスが出ない、しかしウェアハウスのサイズを上げるのは過剰、そんなときに一度検討いただきたい機能ですね!