💴

【Snowflake】ユーザー単位のクレジット集計について

2024/09/04に公開

はじめに

この記事ではSnowflakeのウェアハウスコストをユーザー単位に集計する方法について、最近登場した「query_attribution_history」の利用も含めていくつかの方法を検討します。
(内容は参考程度でお願いします。)

案1:query_attribution_historyで集計

特定期間・特定ウェアハウスについてquery_attribution_historyを使ってユーザー単位に集計してみます。

クエリ
SELECT
  user_name,
  sum(CREDITS_ATTRIBUTED_COMPUTE)
FROM
  snowflake.account_usage.query_attribution_history
where
  start_time between '2024-08-24' and '2024-09-03'
  and warehouse_name = 'COMPUTE_WH'
group by
  user_name
結果

ユーザー単位にクレジットが集計できている。

案1の問題点

リファレンスにもありますが、「credits_attributed_compute」にはクエリ実行のクレジット使用量のみが含まれており、アイドル時間は含まれていません。
そのため5秒のクエリを実行した場合は5秒のクレジットが計上されていると思われますが、実際にはウェアハウスが最低でも1分起動してしまうため差が生まれるのではないかと思います。

検証してみる

warehouse_metering_historyから集計した実際のクレジットと比較してみます。

クエリ
select
  t1.*,
  t2.MET_CRE
from
  (
    SELECT
      date_trunc('day', start_time) as date,
      WAREHOUSE_NAME,
      sum(CREDITS_ATTRIBUTED_COMPUTE) as ATT_CRE
    FROM
      snowflake.account_usage.query_attribution_history
    where
      start_time between '2024-08-24' and '2024-09-03'
      and warehouse_name = 'COMPUTE_WH'
    group by
      1,
      2
  ) t1
  left join (
    select
      date_trunc('day', start_time) as date,
      WAREHOUSE_NAME,
      sum(CREDITS_USED_COMPUTE) as MET_CRE
    from
      snowflake.account_usage.warehouse_metering_history
    where
      start_time between '2024-08-24' and '2024-09-03'
      and warehouse_name = 'COMPUTE_WH'
    group by
      1,
      2
  ) t2 on t1.date = t2.date
order by
  1
結果

予想通りquery_attribution_historyの「CREDITS_ATTRIBUTED_COMPUTE」のほうが、warehouse_metering_historyよりも低くなっています。

案2:総実行時間に対するユーザー単位の実行時間割合からコスト按分

次に、query_historyからユーザー単位の実行時間割合を計算し、それをwarehouse_metering_historyのウェアハウスコストに按分するやり方を試してみます。

select
  user_name,
  execution_time_user,
  execution_time_all,
  execution_time_user / execution_time_all as exec_percentage,
  credits_all, 
  credits_all * (execution_time_user / execution_time_all) as credits_user
from
  ( -- ユーザー単位のクエリ実行時間を集計
    select
      user_name,
      sum(execution_time) execution_time_user
    from
      snowflake.account_usage.query_history
    where
      start_time between '2024-08-24' and '2024-09-03'
      and warehouse_name = 'COMPUTE_WH'
    group by
      1
  ) t1
  cross join (
    -- クエリの総実行時間を集計
    select
      sum(execution_time) execution_time_all
    from
      snowflake.account_usage.query_history
    where
      start_time between '2024-08-24' and '2024-09-03'
      and warehouse_name = 'COMPUTE_WH'
  ) t2
  cross join(
    -- ウェアハウスの総コストを集計
    select
      sum(CREDITS_USED_COMPUTE) as credits_all
    from
      snowflake.account_usage.warehouse_metering_history
    where
      start_time between '2024-08-24' and '2024-09-03'
      and warehouse_name = 'COMPUTE_WH'
  ) t3
結果

この案であれば、
ユーザー単位のクレジットの総数=ウェアハウスクレジットの総数
は実現できそうです。

案2の問題点

単純に実行時間で按分すると、ウェアハウス・リザルトキャッシュなどで同じクエリなのに実行時間が短いユーザーも出てきてしまうので不公平があるかも。

おわりに

Snowflakeはウェアハウス単位にコストが発生しますが、実際の運用においてはウェアハウス単位ではなく組織やユーザー単位などで見たい場合も多いです。
query_attribution_historyは参考として確認するのはよいと思いますが、おそらく実コストと乖離がある点は注意しておいたほうがよいかと思いました。

Discussion