クラウドデータウェアハウス(Amazon Redshift)のコスト削減した話


Loading...

グループデータマネジメント部の須藤です. 日々の業務はデータ基盤の開発や運用を行っています.

今回はAWSのクラウドデータウェアハウスAmazon Redshiftの費用削減に取り組んだのでそこで得た知見を共有したいと思います. クラウドデータウェアハウスはスケーラビリティやパフォーマンスが費用対効果のバランスが取れているか定期的に見直しする必要があります. 我々が運用しているAmazon Redshiftのクラスタは利用開始してから3年が経過しており,開始当初より利用量が増えて利用パターンが変化していたので効率化に取り組みました.

背景

RedshiftにはプロビジョニングされたクラスタとServerlessの2つの選択肢があります. 我々の運用しているRedshiftは利用開始当初ServerlessがGAでなかったこともあり, プロビジョニングされたクラスタだけで構成されていました.

また,利用開始当初はどの程度の利用量で安定するのか見込みが立てられなかったのでRI (Reserved Instance)の購入をしていない状態でした. 現在は今の利用状況が少なくとも1年間は続きそうという見込みが立った状況となりました.

それらを踏まえて,今回は各クラスタについて以下の2つのうちのどちらかが実施できそうという目算があって費用削減の調査を実施しました.

  • 既存のプロビジョニングされたクラスタにRI (1年)を適用する
  • プロビジョニングされたクラスタをServerlessに移行する

Redshiftクラスタはdev (開発目的)・stg (本番環境相当)・prod (本番環境)の3つを運用しています.この3つのクラスタが費用削減の対象となります.

料金体系の比較

クラウドデータウェアハウスの料金は,データプラットフォーム統合プロジェクトの紹介 - KADOKAWA Connected Engineering Blogで登場したSnowflakeもそうなのですが,主にコンピューティングコストとストレージコストで構成されています.

プロビジョニングされたクラスタではクラスタの起動時間に対してコンピューティングコストがかかってきます.Redshiftの現状の利用状況は定型的なワークロードだけが動いているわけではなく,分析者のアドホック分析が行われていたり,どんな時間に定期実行が追加されるか読めない状況でした.そのため,定時でクラスタを停止するといった運用が難しく,プロビジョニングされたクラスタは365日24時間起動する想定となります.

Serverlessではワークロードを実行している時間に対してコンピューティングコストがかかってきます.そのため,ワークロードを実行していない時間が多い場合にServerlessの方が費用削減が見込めそうです.Serverlessの場合はクラスタを停止するといった「Redshiftを利用できない時間」を用意しなくとも「ワークロードが実行されていなければ課金されない」というところが大きなメリットになります.

現時点 (2024-03)ではアジアパシフィック (東京) リージョンのプロビジョニングされたクラスタとServerlessのコンピューティングコスト*1は以下のようになります.

Redshiftの種類 単価 備考
プロビジョニングされたクラスタ 1.278 USD/node/hour (ra3.xlplus)
3.836 USD/node/hour (ra3.4xlarge)
15.347 USD/node/hour (ra3.16xlarge)
ra3.xlplusはメモリ基準のRPU換算で2 RPU/node
ra3.4xlargeはメモリ基準のRPU換算で6 RPU/node
ra3.16xlargeはメモリ基準のRPU換算で24 RPU/node
Serverless 0.494 USD/RPU/hour 1RPUあたり16GiB
Redshift Spectrumの費用を含む
最小課金時間60秒
秒単位の課金

単価の特徴としては,プロビジョニングされたクラスタとServerlessのメモリ容量を揃えると少しだけServerlessが安くなるような傾向があります.しかし,プロビジョニングされたクラスタとServerlessはCPUパフォーマンスとメモリの比が違っていて,クエリ実行時のパフォーマンスが変わってくるのでそのまま費用を比較することはできません.

また,Serverlessにはワークロードに利用するコンピューティングリソースを自動でスケーリングする機能があります.この機能でのスケーリングはそれほど瞬間的に行われるわけではないので (体感的には10分くらい経過したらスケールアップする感じでしょうか),初期のリソース量となるベースRPUを何にするのかがパフォーマンス視点でもコスト視点でも重要な要素になります.

ストレージコストに関しては,プロビジョニングされたクラスタとServerlessでの単価は同じになるので基本的に考慮には入れませんでした.

実行するクエリの比較

プロビジョニングされたクラスタで動作しているクエリは,システムビューを参照していなければ基本的にはServerlessでも同じクエリが動作します.

STL_*, SVL_*などのシステムビューには,名前が違っていたり一部ないものもあります.

docs.aws.amazon.com

speakerdeck.com

上記スライドでも,主なシステムビュー対応表として以下のように示されています.

用途 プロビジョニングされたクラスタ Serverless
Copyの確認 STL_LOAD_ERRORS SYS_LOAD_ERROR_DETAIL
クエリ確認 STL_QUERY
STL_QUERYTEXT
SYS_QUERY_HISTORY
SYS_QUERY_DETAIL
SYS_EXTERNAL_QUERY_DETAIL
UNLOADの確認 STL_UNLOAD_LOG SYS_UNLOAD_HISTORY

実際に利用者がServerlessに存在しないシステムビューを使ったクエリを実行している可能性があるのでServerless環境で実際に動いているクエリを実行してみる必要がありそうです.

見積もり

各クラスタにおいてRIとServerlessのケースで見積もりを行って安い方に移行を行います.

結果的に「devとprodにRIの適用」,「stgをServerlessに移行する」ことになりました. 以降は具体的にどのような見積もりを行ったのかを示していきます.

RIの見積もり

RIの見積もりは簡単に行うことができます.料金 - Amazon Redshift | AWSから条件を入力すると何%費用削減できるのかを確認できます.

Serverlessの見積もり

Serverlessの見積もりは二段階に分けて行いました.

  1. 現行のプロビジョニングされたクラスタと同程度のパフォーマンスのRPUの特定
  2. 現行のプロビジョニングされたクラスタの実行時間の総量から特定したRPUにて費用の計算

ServerlessはCPUパフォーマンスとメモリ比がプロビジョニングされたクラスタと異なるため,ワークロードによっては同じくらいの費用でも期待するパフォーマンスが得られない可能性があります.そのため,まず現行のクラスタに相当するのが何RPUであるのかの特定を行いました.

Serverlessの見積もりでは現行のワークロードに影響を与えないようにスペックが同じクラスタを別で立てて検証しました.

見積もりの結果,stgはServerlessに移行することで費用の90%を削減できる見込みが立ちました.stgはdevやprodと比べて圧倒的に利用量が少なくてクラスタに余力がある時間が多いうえに,stgはprod相当の高いスペックを持っているためプロビジョニングされたクラスタだと効率が悪かったようです.

RPUの特定

RPUの特定は「特定のワークロードをプロビジョニングされたクラスタとServerlessで実行して実行時間が同じになる最低RPUを探す」といった方法を取りました. 最低RPUを探しているのはスペックが高すぎてパフォーマンスが頭打ちしている可能性があるためです.

特定のワークロードとしては今回はTPC-DSというベンチマークを利用して測定しました.TPC-DSは分析データにありがちなスタースキーマのデータモデルに対してクエリを行うため検証としては妥当だと判断しました.

RedshiftではプロビジョニングされたクラスタでもServerlessでも以下のリポジトリにあるクエリを利用して簡単にTPC-DSのデータを用意することもできます.

github.com

実行時間の総量の算出

実行時間の総量はSYS_QUERY_HISTORY - Amazon Redshiftを利用して算出しました.このシステムビューは7日程度のデータしか含まれていないため注意が必要です.

select
  Date(start_time) as exec_date,
  sum(datediff('second', start_time, end_time)) as exec_seconds
from
  sys_query_history
group by
  1
order by
  1 desc
;

ここまでで{実行時間の秒数}/3600*{特定したRPUの数}*0.494 USD/RPU/hourでServerlessへ移行したときの見積もりの費用が出ます.

ただし,この見積もりは以下の前提を置いています.

  • Serverlessでの課金最小は60秒だがこのオーバーヘッドはほぼかからないとして無視している
    • 十分に60秒以上のクエリが多く支配的である
  • 特定したRPUで十分な性能がありほとんどのケースで自動でのスケーリングが発生しない
    • ほぼすべてのクエリがベースRPUで実行される

Reserved Instanceへの移行プロセス

RIは見積もりだけでなく移行も簡単です.プロビジョニングされたクラスタの設定変更や再作成・移行といった手順を踏む必要なく,実際の環境で使っているスペック・ノード数分のRIを購入するだけで済みます.

煩雑になりがちな権限やデータの移行,データ共有の再作成といった手順が不要になるのがうれしいです.

Serverlessへの移行プロセス

Serverlessへの移行は以下のように進めました.

  1. プロビジョニングされたクラスタからの移行方法の検証
  2. 利用者側での検証
  3. 移行実施

RIへの移行とは違ってServerlessに移行する場合は様々な不確定要素がでてくるため,段階的に進めて移行プロセス中に問題があればRIをバックアッププランとして採用する方針としていました.

不確定要素には以下のようなものがありました.

  • プロビジョニングされたクラスタからServerlessへの移行方法
    • ユーザ
    • データ
    • 権限
    • データ共有
  • 既存のクエリがそのまま実行できるか
    • 利用者側の対応が必要な場合は対応可能な量か
  • 特定したRPUでのパフォーマンスが十分か
    • プロビジョニングされたクラスタとまったく同じスペックではない

移行方法に関しては,プロビジョニングされたクラスタのスナップショットから移行できることが公式ドキュメントで触れられていますが,ユーザが認証情報そのまま継承されるのかや承認が必要なデータ共有がどうなるのかについて読み取ることができなかったのでスナップショットからの復元を実施して確認することにしました.

docs.aws.amazon.com

「既存のクエリがそのまま実行できるか」は,定期的ではないクエリを含めて実行するクエリの比較の節で述べたシステムビュー変更が重大な問題になるのかどうかを利用者での検証を行って調べる必要があります.

また,「特定したRPUでのパフォーマンスが十分か」も一般的なワークロードでRPUを特定しているので十分なパフォーマンスとなっているかを利用者にチェックしてもらいます.

プロビジョニングされたクラスタからの移行方法の検証

まずは以下の公式ドキュメントに沿ってスナップショットから移行を行ってみました.

docs.aws.amazon.com

その結果,次のことが判明しました.

  • ユーザはそのままで,パスワードを利用している場合はパスワードも同じまま認証できる
  • データや権限は引き継がれているが,もちろんスナップショット時点のものとなる
  • データ共有はデータベースが引き継がれるが利用できない状態になっていた

データ共有だけ移行方法を検討する必要がありました.データ共有はデータの共有元Redshiftで共有先のnamespaceにデータ共有の許可を出さないといけません.namespaceはクラスタ毎に存在するため,スナップショットからServerlessに復元した際も新たにデータ共有元で許可を出す必要があるようです.

ここで注意が必要な点としては,データ共有のデータベースはスナップショットから復元した際には残ってしまっているので一旦drop databaseしてからデータ共有のプロセスをやり直す必要があります. これによって,データ共有に関する権限が消えてしまう点にも注意が必要です.今回はdrop databaseをしてしまう前に以下のビューを利用してgrant文を取得しておく方法を採用しました.

github.com

作成したビューに以下のようなクエリでgrant文を取得しておき,データ共有を再設定した後に取得したgrant文を実行することで移行前の環境の権限を再現することができます.

select ddl from v_generate_user_grant_revoke_ddl where ddltype='grant';

利用者側での検証

利用者側での検証の際にはあらかじめどの時点でのスナップショットで検証したいのかヒアリングしてServerless環境を作成しました.

利用者にはその時点のデータであることを意識してもらいながら,既存のクエリがそのまま実行できるか,パフォーマンスが十分かを確認してもらいました.

Redshiftの利用方法によってはもっとたくさんの問題が出てもおかしくなかったのですが,今回の移行では幸運にも以下の問題だけしか見つかりませんでした.

  • システムビューのSVL_STORED_PROC_MESSAGESを使っているがServerlessにはない

SVL_STORED_PROC_MESSAGESは代用のSYSモニタリングビューSYS_PROCEDURE_MESSAGESがあり,利用者側でも対応可能であると,問題ないことが確認できました.

移行実施

移行スケジュールの大枠としては,移行実施日時,クラスタ停止日,クラスタ削除日を決めました.

移行実施日時は,スナップショット取得時のデータでServerlessに復元されるので利用者全体でデータの書き込みがない時間に設定する必要があります.スナップショット取得後に間違えて移行前のクラスタに書き込みしてしまうとServerlessに反映されないままになってしまいます.利用者側の検証環境の作成時に「スナップショット作成からクエリ実行できるようになるまで」が1時間あれば十分だと判明していたのでメンテナンス期間を1時間として,その間書き込みを行わないようにすべての利用者と調整して日時を設定しました.

移行を行うと利用者側でServerlessの接続URLへの変更を行う必要があります.移行実施日時からクラスタ停止日までは読み込み (select)だけのクエリはデータが最新でない可能性がありますが,プロビジョニングされたクラスタにクエリを投げてもらっても問題ありません.利用者側でもすべてのクエリをいきなりServerlessの接続URLに変更することができない可能性があったので,「データが最新でない」というリスクを容認してクラスタ停止まで猶予を持たせることにしました (接続失敗するより業務への影響が少ないという判断).

クラスタ停止日からクラスタ削除日の期間は万が一の時に備えたリカバリできる期間になります.クラスタを停止していればストレージコストだけしか費用が掛からず影響が小さいので念のため設定しておきました.

移行実施は事前に手順をよく検討していたこともあり,問題なく順調に終了しました.

費用削減効果

RIはもちろん見積もりをした結果と同じだけの割合の費用削減ができました.

Serverlessに移行したstgに関しては見積もり時は90%の費用削減を見込んでいたのですが,実際に移行してみると50%の費用削減となっていました.

stgの見積もりとの違いを調査したところ,不定期に60秒以下のクエリが増大しているタイミングで予想よりも費用が発生していることが確認でき,60秒以下のクエリで加算される費用でほとんどの見積もりとの違いを説明することができました.Serverlessでは以下のクエリでユーザごとの60秒以下のクエリ数を確認することができます.

select
  u.user_name "user_name",
  trunc(start_time) "date",
  count(distinct query_id) "number_of_jobs"
from
  sys_query_history q
join
  svv_user_info u
on
  q.user_id = u.user_id
WHERE
  execution_time != 0
  and execution_time < 60 * 1000 * 1000
group by
  1, 2
order by
  1, 2 asc
;

結果的に60秒以下のクエリ数の影響を甘く見ていたことが見積もりと実績の乖離につながりました.実際にこれを踏まえて見積もりを改善しようと考えるとなかなか難しいのかもしれません.RPUの確保はクエリ毎に発生するわけではなく,Serverlessのワークグループ単位で行われるようなので60秒以下のクエリが連続して実行されていたり,他の実行時間の長いクエリが裏で実行されていたりするとほぼ影響がなくなりそうに思えます.そうなると,クエリの履歴から60秒以下のクエリの数を数えてもそれらが費用に影響を及ぼすかどうかはクエリの投げられ方次第になってしまうので,実際に移行してみないことには見積もりが難しそうというのが所感です.

また,stgの見積もり時に取得したSYS_QUERY_HISTORYは直近7日程度のデータしか含まれていなかったので局所的に少ない実行時間の総量となっていた可能性もあります.この点の改善案としては,別のテーブルに定期的にコピーして保持期間の長いクエリ履歴テーブルを作成してから見積もりすることも考えられます.

まとめ

Redshiftの費用削減の事例とその時に得られた知見について紹介しました.devとprodはRI適用,stgはServerlessへの移行を行いました.

RI適用とServerless移行に関するメリットとデメリットは以下になります.

メリット デメリット
RI適用 簡単に実施できる
利用者影響がない
見積もり通りの費用削減
RIなので一定期間分の費用の支払いが確約される
Serverless移行 自動的なクラスタ起動停止管理
利用状況変更への柔軟性が高い
利用者影響が大きい
見積もりの難しさ

RI適用は「簡単に実施できる」や「見積もり通りの費用削減」はうれしいメリットがあり,支払いが確約されるものの予測のしやすいデメリットなので堅実な費用削減方法だと感じました.

Serverlessでは移行を実施してみて移行や見積もりの難しさを体感させられました.その一方で,Serverlessは自動的にクラスタの起動停止を管理してくれるようなもので,低頻度・不定期実行・高パフォーマンスといった要件の場合に大きなメリットがあります.

また,今回はServerlessの見積もりを既存クラスタのワークロードの実行時間ベースで行いましたが,より見積もりの精度を上げるためには違う方法を採用した方がいいかもしれません.今回のServerless見積もりでの課題は以下2点でした.

  • ベースRPUでスケーリングがほぼ発生しないという仮定を置く是非
    • 今回は移行したワークロードをみてもスケーリングが発生していなかったので影響ありませんでした
  • 60秒以下のクエリの影響の見積もり方法

特に60秒以下のクエリの影響は場合によっては大きくなってしまうので,今回のような見積もり方法を採用するのであれば,大きな費用のアドバンテージがある場合にだけ移行する意思決定をした方がいいように思えます.今回のケースはそれを意図していなかったのですが,費用削減が90%とあまりにも大きかったので60秒以下のクエリの影響があっても50%の費用削減になりました.

Serverlessへの移行はそういった見積もりと違う結果となるリスクがあるので,普段からプロビジョニングされたクラスタでもServerlessでも動くクエリにしておいて移行コストを軽くしておくといいかもしれません.具体的には,プロビジョニングされたクラスタでSYS モニタリングビュー - Amazon Redshiftを使ったクエリに修正することになります.

また,今回は適切なRPUの特定にTPC-DSを利用しましたが,利用者に実際のワークロードを実施してもらう方法もあると思います.今回は利用者への影響を減らす目的で見積もりに一般的なデータを使用しました.そのRPUで利用者のパフォーマンス確認も問題ないことがわかったのでそのまま進めましたが,最初から利用者のワークロードでRPUを特定できるのであればそちらの方が間違いないはずです.

最後に,Serverlessへの移行は思ったより大変でした.具体的な見積もり方法はネットサーフィンしても参考になる情報が得られなかったですし,実際にスナップショットからServerlessに復元するとデータ共有の問題もありました.この記事の知見がプロビジョニングされたクラスタからServerlessへの移行の参考になると幸いです.

*1:Amazon Redshiftの正確な費用は公式ドキュメントで確認してください