NTTドコモR&Dの技術ブログです。

ドコモ3年目社員がRedshiftの10年モノの技術負債解消にチャレンジしてみた

はじめに

NTTドコモ データプラットフォーム部(以下DP部)木村です。 NTTドコモでは「通信」だけでなく「決済・保険・投資」「エンタメ」をはじめとした様々なサービスをコンシューマー向けに提供しています。 DP部では様々なサービスに対して、データドリブンの価値創造をあたりまえにすべく、データ基盤開発・データ分析・ナレッジ集約・データ活用人材育成を実施しています。

本記事では私が3年目社員だった22年度に取り組んだ、約10年前から稼働しているデータ基盤における、日中帯のパフォーマンス低下を解消するための取り組みについて一部紹介します。

システム概要

RedshiftはRA3ノードタイプを利用しています。EC2ではテーブル形式にデータを加工するための処理を実施しており、テーブル形式に加工したデータを分析用データにRedshiftで加工しています。 このRedshiftに格納した分析用データをSageMakerやBIサーバーを用いて利用者は日々分析活動をしています。 このRedshiftはデータ加工・データ分析の要となっており、日中帯のパフォーマンスが低下してしまうことを解決したいと考え原因を調査しました。

システム構成図

長時間Vacuumの回避

Vacuumとはパフォーマンス向上・維持のために必要な処理でデータの再ソートや削除されたデータにおけるディスク領域の開放を行う処理です。 日中帯のパフォーマンス低下の原因はRedshiftのコンピュートノードのCPU利用率が100%付近に張り付いていることが原因の一つと考え、特に処理が重かったVacuumの改善に着手することとしました。

原因として挙げられたのが下記2つです。

  • ETL処理がRedshiftのような列指向データベースに最適化されていない箇所がある
  • Vacuumの頻度・範囲が過剰

列指向データベース

前提知識として、Redshiftのような列指向データベースの特徴について簡単に紹介します。 データ分析で利用するデータベースは100を超えるような列から必要な列だけを効率的に抽出するといった処理に強いことが望ましいです。(OLAP)

一方、ECサイトの在庫管理システムに使われるデータベースは、ランダムにアクセスされるような書き込みに対応し、データに矛盾が生じないことに重きを置いています。(OLTP)

このうち、データ分析でよく使う処理に強いのが列指向データベースです。 列指向データベースとは簡単にいうとテーブルのデータを行単位ではなく、列単位でストレージ上に保持するデータベースを指します。データ圧縮やデータ抽出には優れている一方で、データの更新処理は苦手とします。

簡単に苦手な理由を説明します。 下記の図のようにデータを一行追加したいとします。列ごとにデータを保持しているため、データの順序は列ごとに同じになるよう調整する必要があります。全ての列に対して同じ位置にデータを挿入する必要があり、データ量が増えるにつれ更新作業に負荷がかかるのがわかると思います。これは削除処理にも同じことがいえるため、更新処理や削除処理は苦手です。 そのため、できる限り更新処理や削除処理を発生させないことがパフォーマンスを高水準に保つ上で重要となります。

列指向データベース

参考文献 Martin Kleppmann 著、斉藤 太郎 監訳、玉川 竜司 訳『データ指向アプリケーションデザイン』オライリー・ジャパン、2019

Vacuumが走りにくい処理への変更

Truncateの積極活用

データ加工処理を見直したところ、DELETE FROM table; となっている箇所を多数発見しました。処理をTruncateに切り替えても問題ないことを確認し、順次変更しました。 DELETE文では削除対象としてデータをマークするだけで物理的には削除されておらず、Vacuunの実行にてディスク領域から解放されます。 Truncateを用いれば、Vacuumを待たずしてディスク領域を解放するためVacuumが発生しません。

私たちの環境ではかなり大きなテーブルの日次洗い替え処理が存在し、6時間以上vacuumに時間がかかっていたテーブルが上記処理に切り替えることでVacuum時間をほぼ0にすることができました。

時系列テーブルの使用

履歴を一定期間保持する大きなテーブルに有効です。 保持期間ごとに別テーブルを作成し、分析向けにはそれらのテーブルをUNION ALL したViewを利用してもらいます。 一つのテーブルにまとめてデータを保持していた場合、保持期間が切れたデータの削除にはDELETE文が必要となり、重いVacuum処理が必要となります。 時系列テーブルを利用すると、保持期間が切れたテーブルに対してDROPをすることとなり、DELETEと比べ処理が軽く、タイムスタンプでソートしていた場合Vacuumも必要にならないのが利点です。

私たちの環境ではBIツールに蓄積された数々のレポートの改修・移行コストと予想される効果を考えて過去分テーブルを時系列テーブルへの変更する開発をしていませんが、新規で開発する履歴系テーブルに関しては積極的に時系列テーブルを使用する予定です。

https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/vacuum-time-series-tables.html

ディープコピーの実行

Vacuumにどうしても時間がかかる巨大なテーブルに関してはディープコピーの実行が有効とされています。 下記のAWS公式ドキュメントに記載のとおり、複数やり方はありますがディープコピーとは、中身が同じテーブルを作成してしまい、元のテーブルと入れ替える処理です。 この処理はVacuum処理より軽いため、どうしてもVacuumに時間がかかるテーブルには採用を検討するべきです。 注意点として、ディープコピー実行中はそのテーブルに対する更新作業はNGとなるので、頻繁に更新が必要なテーブルに利用はできません。

私たちの環境ではTruncateの活用でVacuum時間をある程度軽減できたため、過去分のテーブルに関してはディープコピーを実施しておりません。今後、巨大テーブルを開発する際には選択肢として利用する予定です。

https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/performing-a-deep-copy.html

Vacuumの頻度・範囲見直し

私たちの環境ではテーブル数が9000以上存在していますが、毎日全てのテーブルに対してVacuumを実行してました。 Vacuumを行う閾値にテーブルの状態が到達しておらず実際には処理がスキップされるテーブルが多数ですが、これだけの数のテーブルが存在するとスキップにかかる時間もそれなりのものになるため、Vacuumの頻度と範囲を見直すこととしました。 結果、平日のVacuum時間を減少させることに成功し、その引き換えとして休日のVacuum時間は増加しましたが、分析利用者がRedshiftを休日に使うことはないので以前と比べリソースを上手に使えているといえます。

  • 基本的にはAuto Vacuumに任せる
  • 週末だけ全てのテーブルにVacuum実施
  • 平日は更新の激しいテーブルに絞ってVacuum実施
    • Vacuumのログやテーブルの更新頻度・量を確認し決定
    • 対象のテーブルをリスト化し、Vacuumするスクリプトを開発しジョブ管理サーバーで運用
      • Vacuumの対象指定は一つのテーブルずつしかできないので注意

他にも改善策として挙げられるもの

Concurrency Scalingの導入

Concurrency Scalingが有効になっている場合、キューが滞留したタイミングで一時的にクラスターを追加し、並列処理してくれます。 一部制約もありますが、1日あたり1時間の無料枠もあるのでぜひ試してみてください。

https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/concurrency-scaling.html

Redshift Serverlessの導入

ETL・ELT処理を行うRedshiftと利用者が利用するRedshiftを環境ごと切り分ける方法もとることができます。 RedshiftのうちRA3インスタンスタイプの場合、Data Sharingというクラスタ間でデータのコピーや移動をすることなくデータを共有することができる機能があります。 これを用いて、分析者用Redshift Serverlessを作成し、分析クエリはこの環境からData Sharingされたデータに対して発行する構成が取れます。 こうすることでETL・ELT処理を行うRedshiftの負荷状況に左右されず分析活動が可能となります。 また、Redshift Serverlessは通常のRedshiftと異なり従量課金かつ自動的にスケールするため、分析クエリのような波があるユースケースに適しています。

https://aws.amazon.com/jp/redshift/redshift-serverless/

おわりに

今回の取り組みの結果、日中帯にCPU使用率が100%付近に張り付くことはなくなり、Redshiftのパフォーマンスが低下していることを感じることもなくなりました。 Redshiftに限らず、Snowflake・BigQuery等どのデータウェアハウスを利用するにしても、アーキテクチャを理解してシステム設計しなければ、性能を引き出すことはできません。 今回の取り組みを通して、アーキテクチャに寄り添うことの大切さと積みあがった技術負債を解消するのは大変だということが身に染みて理解できました。 今回取り組んだような簡単な部分の改修でも大きく改善することもあるのでRedshiftの性能を引き出したい方の参考になると幸いです。