RedShiftの列圧縮タイプを見直し、ディスク費用を節約する

こんにちは。データサイエンティスト兼、データ基盤エンジニアのshobyです。

今回は、RedShiftを長年運用していく中でディスク使用量が肥大化していく問題に対して、列圧縮タイプを見直し、ディスク費用を節約する方法をご紹介します。

概要

  • RedShiftのデータ容量肥大化問題
  • RedShiftの列圧縮タイプとは
  • 容量の大きいテーブルを見つける
  • 最適な列圧縮タイプを分析する
  • テーブルを作り直して、データを入れ直す
  • TVISION INSIGHTSでの実例

RedShiftのデータ容量肥大化問題

RedShiftにはデータが蓄積された結果、ディスク容量が肥大化し、必要な費用が日々増大していく問題が存在します。

RedShiftのインスタンスはEC2とは異なり、インスタンス辺りのディスク容量を自由に設定することができません。

そのため、高パフォーマンスなインスタンスが欲しい場合には、インスタンス辺りのディスク容量を妥協しなければならず、 容量が肥大化すると大量のインスタンスが必要になってしまいます。

つまり、ディスク容量が増えれば増えるほど、必要な費用がガンガン増えていく、という状況が生まれます。つらい...

この状況を改善するには、データを削除するか、データを圧縮するかの二つしかありません。 今回はデータを圧縮することで、コストを抑える方法をご紹介します。

RedShiftの列圧縮タイプとは

列ごとに指定されたデータの圧縮方式のことです。 RedShiftは列指向データベースであり、列ごとに最適な圧縮方式を選択することで、容量を削減することができます。

docs.aws.amazon.com

未指定時のデフォルトでは、以下のルールで列圧縮タイプが指定されています。

  • ソートキーとして定義されている列には、RAW 圧縮
  • BOOLEAN、REAL、または DOUBLE PRECISION データ型として定義されている列には、RAW 圧縮
  • 他のすべての列には LZO 圧縮

また、未指定の場合でも、COPYコマンドを使用してS3からデータをインポートした場合、 初回インポート時のデータセットに対する最適な列圧縮タイプが自動設定されます。

docs.aws.amazon.com

COPYコマンドによる自動圧縮はテーブルが空のタイミングしか効果がないという点にご注意ください。 データが少ない初期状態と、多くのデータが挿入された後では、最適な列圧縮タイプが変わる可能性があります。

今回は、これらのデフォルト設定のテーブルたちに、最適な列圧縮タイプを設定することを考えます。

容量の大きいテーブルを見つける

闇雲に圧縮をしても効果が薄いため、まずは、容量の大きなテーブルを見つけます。*1 容量の大きなテーブルほど、圧縮方式の最適化を行なった際の、容量削減効果が高くなりやすいためです。

以下の記事で紹介されているクエリを利用すると、テーブルごとの容量を把握し、容量の大きいテーブルを見つけることができます。

qiita.com

最適な列圧縮タイプを分析する

ANALYZE COMPRESSIONコマンドを使用することで、最適な列圧縮タイプを分析することができます。

ANALYZE COMPRESSION target_table

docs.aws.amazon.com

ANALYZE COMPRESSIONコマンドは、最適な列圧縮タイプと、その圧縮を使用した際の推定減少パーセントを表示してくれます。

圧縮タイプがRAWの列を分析した後などは、50%以上の容量減少が見込める場合もあります。 心が躍りますね。

注意点として、あくまで一部のデータをサンプリングした結果なため、実際にその容量が減るわけではないことをご注意ください。 サンプル数は、COMPROWSというパラメータで増やすことができます。

テーブルを作り直して、データを入れ直す

残念なお知らせですが、RedShiftはALTER TABLEでは列圧縮タイプを変更することができず、 新しくCREATE TABLEをし、旧テーブルからデータを入れ直す必要があります。

この際、容量の大きなテーブルが一時的に二重に存在することになるため、 ある程度ディスク容量にバッファが必要になる点をご注意ください。

作業は以下の手順で進めます。*2

  1. RedShiftクラスターのスナップショットを取る
  2. 既存のテーブル定義の確認
  3. CREATE TABLE文の作成と発行
  4. 新テーブルに既存テーブルと同等の権限を付与
  5. INSERT文を用いて旧テーブルのデータを新テーブルに移す
  6. ディスク容量の差を確認する
  7. 旧テーブルをリネームし、新テーブルを旧テーブルと同じ名前にする
  8. 旧テーブルをDROP TABLE

RedShiftクラスターのスナップショットを取る

万が一何かあっても戻せるように、作業前にスナップショットを取っておきましょう。

既存のテーブル定義の確認

まず、既存テーブルのテーブル定義を確認し、全く同じCREATE TABLE文を再現します。

DataGripであれば、テーブルを右クリック>SQL Scripts>Generate DDL to Clipboard で、 既存テーブルと全く同じCREATE TABLE文をクリップボードにコピーすることができます。

CREATE TABLE文の作成と発行

既存のCREATE TABLE文の各カラムにENCODINGを追加し、実行します。

Before

CREATE TABLE big_data_table
(
  id BIGINT,
  value DOUBLE PRECISION
);

After

CREATE TABLE big_data_table_compressed
(
  id BIGINT ENCODE ZSTD,
  value DOUBLE PRECISION ENCODE ZSTD
);

新テーブルに既存テーブルと同等の権限を付与

新しくテーブルを作り直すと権限が真っさらになってしまうため、 既存テーブルと同等の権限を付与し直す必要があります。

権限周りのオペレーションについては以下の記事をご参照ください。

tech.tvisioninsights.co.jp

INSERT文を用いて旧テーブルのデータを新テーブルに移す

以下のように、INSERT文を用いて旧テーブルのデータを新テーブルに移します。

INSERT INTO big_data_table_compressed (SELECT * FROM big_data_table)

INSERTが終わったら、念のためデータの件数に違いがないことを確認しておきましょう。

ディスク容量の差を確認する

Before・Afterでディスク容量の差を確認しておきます。

qiita.com

効果がなかったようであれば、新テーブルをDROPして最初からやり直します。

旧テーブルをリネームし、新テーブルを旧テーブルと同じ名前にする

効果があったようであれば、新テーブルを使いましょう!

以下のように旧テーブルをリネームし、新テーブルを旧テーブルと同じ名前にします。

ALTER TABLE big_data_table RENAME TO big_data_table_old;
ALTER TABLE big_data_table_compressed RENAME TO big_data_table;

旧テーブルをDROP TABLE

あとは、古いテーブルをDROPするだけです。

DROP TABLE big_data_table_old;

TVISION INSIGHTSでの実例

TVISION INSIGHTSでは、約3年間に渡る秒単位のテレビ視聴ログデータが蓄積された結果、 RedShiftのディスク容量が肥大化し、ディスクフルのアラートと費用に怯える生活が続いていました。

その改善策として列圧縮タイプの最適化を行った結果、1TB以上の容量削減に成功し、大幅な費用削減に成功することができました。

まとめ

RedShiftは長年運用することでディスク容量が肥大化し、かかる費用が増大していく問題が存在します。 容量を削減するには不要なデータの削除とデータの圧縮が有効です。

列圧縮タイプを変更する場合には、効果の大きそうな容量の大きなテーブルから着手し、 最適な圧縮タイプを分析し、テーブルを作り直すことで圧縮方式を変更することができます。

*1:「推測するな、計測せよ」とはよく言われますね

*2:こちらのドキュメントを参考にしています。