Amazon Redshift テーブル設計詳細ガイド:Part 4 圧縮エンコーディング
著者 Zach Christopherson は Amazon Redshift チームのシニアデータベースエンジニアです。
Part 1: Preamble, Prerequisites, and Prioritization(序文、事前準備、優先順位付け)
Part 2: Distribution Styles and Distribution Keys(分散スタイルと分散キー)
Part 3: Compound and Interleaved Sort Keys(Compound と Interleaved ソートキー)
Part 4: Compression Encodings(圧縮エンコーディング)(本稿)
Part 5: Table Data Durability(テーブルデータの永続性)
このブログの第4部では、Amazon Redshiftにおける圧縮の為の、列エンコーディングの適用有無、理想的な列エンコーディングの決定方法、および自動的な圧縮の振る舞いについて説明します。
データベースシステムでのデータ圧縮は新しいものではありません。しかしながら、展開には大きなオーバーヘッドがあることから、パフォーマンスを向上させるのではなく、データフットプリントを削減するために歴史的には使用されてきました。 Amazon Redshiftにおいては、列エンコーディングすることは、データフットプリント削減とパフォーマンス向上の両方をすることになります。これは展開のコストがディスクI/Oの削減に対し無視できるほど小さい為です。
Amazon Redshiftテーブル内では、各ブロック内の値を圧縮するために使用されるエンコーディングを各列にて指定できます。一般的に、Amazon Redshiftクラスタ内のほぼ全ての列に圧縮を使用する必要がありますが、列のエンコードを避ける方がよい場合があります。
最適化された圧縮方法を優先付けする手段は、以前のパートで使用した優先付けの方法とは少し異なります。これは主に、重要なテーブルの多くに対して自動または手動の圧縮を実装していたためです。圧縮対象とするテーブルを決定する際に使用するアプローチは、テーブルごとに圧縮されていないストレージのサイズを測定することに基づいています。
SELECT
ti.schema||'.'||ti."table" tablename,
uncompressed_size.size uncompressed_size,
ti.size total_size
FROM svv_table_info ti
LEFT JOIN (
SELECT tbl,COUNT(*) size
FROM stv_blocklist
WHERE (tbl,col) IN (
SELECT attrelid, attnum-1
FROM pg_attribute
WHERE attencodingtype=0 AND attnum>0)
GROUP BY 1) uncompressed_size ON ti.table_id = uncompressed_size.tbl
ORDER BY 2 DESC NULLS LAST;
事前のクエリ結果を使用し、優先付けすることにより、この簡単なフローチャートの実行にて圧縮するかどうかを決定できます。
圧縮により、現在または将来のストレージフットプリントが削減されますか?
列に圧縮エンコーディングを追加してもストレージが削減されない場合は、圧縮を導入する価値はありません。そのデータにアクセスすると、展開コストがかかります。この展開コストはほとんど無視できますが、圧縮エンコーディングの使用による恩恵がある場合のみ使うことが最良です。
テーブルが既に最小サイズのテーブルである場合、圧縮はディスク上のデータサイズを縮小しません。以前の投稿で定義したv_extended_table_infoビューを使用することにより、圧縮されていない列を持つテーブル、その列が消費している記憶域の量、どのテーブルが最小限のサイズであるか識別できます。
SELECT eti.tablename, eti.columns,
uncompressed_size.size uncompressed_size, eti.size total_size
FROM admin.v_extended_table_info eti
LEFT JOIN (
SELECT tbl,COUNT(*) size
FROM stv_blocklist
JOIN pg_attribute ON tbl=attrelid
AND col = attnum-1
AND attencodingtype=0
AND attnum>0
GROUP BY 1) uncompressed_size
ON eti.table_id = uncompressed_size.tbl
WHERE uncompressed_size.size IS NOT NULL
ORDER BY uncompressed_size.size DESC;
tablename | columns | uncompressed_size | total_size
-----------------+---------+-------------------+--------------------
public.lineitem | 15/16 | 2298 | 26695/114 (4.6677)
public.partsupp | 4/5 | 306 | 4224/48 (0.7385)
public.nation | 0/4 | 24 | 42/42 (0.0073)
public.region | 0/3 | 15 | 30/36 (0.0052)
(4 rows)
次に、クエリ結果セットについて説明します。
- columns: X/Y:
- X 圧縮された列の数
- Y 全部の列の数
- uncompressed_size: テーブル内の圧縮されていない列によって消費された1 MBブロックの合計数
- total_size: T/M (P) :
- T 1MBブロックにおけるテーブルの合計サイズ
- M クラスタのすべてのスライスに少なくとも1つの行が設定されていると仮定して場合のテーブルの最小サイズです
- P テーブルによって消費されたクラスタの合計ストレージの割合
前述の例における結果の解釈は次のとおりです。
- linitemには、2298MBを消費する非圧縮列があります。
- partsuppには、306MBを消費する非圧縮列があります。
- テーブル名 nationの4つの列はすべて圧縮されていませんが、テーブルは最小のテーブルサイズになっているため、これらの列を圧縮することによる結果は得られません。
- テーブル名 regionの3つの列はすべて圧縮されていませんが、テーブルは最小のテーブルサイズになっているため、これらの列を圧縮することによる結果は得られません。
圧縮されていない列を持つテーブルが最小テーブルサイズ以下で報告されていて、将来的にその表のサイズが大きく変化しないと考えると、圧縮ではストレージの占有面積の削減やパフォーマンスの向上は起こらないと結論付けられます。したがって、圧縮はしないでください。
圧縮の結果、行のオフセットが大きくなりますか?
列を圧縮することによるパフォーマンス上の利点は、ディスクI / Oの削減としてあらわれます。このI / Oの削減は、クエリ処理中にテーブルがスキャン用にアクセスされるため、読み取りワークロードに最も大きな影響を与えます。
過度の圧縮によりパフォーマンス低下が引き起こされるのは、1つのエッジケースとして注意することが重要です。稀なパフォーマンス低下は、次の基準を満たす状況下で発生します。
- クエリパターンが非常に圧縮された列に対し、範囲を絞ったスキャンを適用している
- 非常に圧縮された列のブロックごとに多数の値が含まれ、クエリの対象としたい実際の値の数よりも多くの値が含まれている
- クエリパターンに必要な他の列が大きい、または十分に圧縮されていない。その列は十分に圧縮された列のサイズの10倍を超えている
このエッジケースの詳細は、Amazon Redshiftの内部に深く入り込むため、他の場所で詳細な説明を行うことが最も効果的と思っています。
ストレージのフットプリント削減を優先し、大きな行オフセットは劣化の解決になるか?
この劣化が確認された場合は、その列の圧縮効果を低下させることで簡単に軽減できます。これは、エンコーディングの種類を変更したり、その列のエンコーディングを完全に削除したりすることで実現できます。また、大きな列が最適に圧縮されていない場合は、理想的な圧縮エンコーディングで定義することで問題を解決することもできます。
場合によっては、パフォーマンスの問題を解決する唯一のソリューションが、列の圧縮を変更して圧縮の効率を低下させることです。このような場合、カラムのサイズを大きくすることが許容されるトレードオフであるかどうかを判断する必要があります。クラスタがストレージに制約されている場合、大きなクラスタにリサイズするまで、このオプションは機能しない可能性があります。
ストレージに余裕がある場合は、エンコードを変更するかエンコーディングを使用しないことにより、すぐに問題を解決できます。
自動エンコードメソッド
多数のテーブルが圧縮されているが、圧縮エンコーディングの選択を覚えていない場合は、Amazon Redshiftの自動エンコーディング最適化が役立ちます。この効果は異なる2つの方法にて得られます。
CTAS: 先程CTASステートメントを使用してテーブルを作成しました。この最適化では、ソートキーの一部ではないブール値、浮動小数点数または倍精度のデータ型ではない全ての列にデフォルトのLZO圧縮を適用しました。
COMPUPDATEによるコピー: どの列にもエンコーディングのない空のテーブルを作成し、COMPUPDATEオプションを明示的に変更せずにCOPYコマンドを使用してそのテーブルを移入すると、テーブルは自動圧縮分析されます。
これらの基準が満たされると、COPYコマンドはデータを取り込む前に自動圧縮分析を自動的に実行します。このプロセスはまず、Amazon S3からのデータのサブセットをサンプリングしてから、総当りの圧縮比較を実行します。これを実行するために、データを1つずつ列ごとに圧縮します。すべての可能な符号化が実行された後、COPYは比較を行います。そして、最も重要な圧縮の結果となるエンコーディングは、そのテーブルの列エンコーディングとして定義されます。このプロセスの後、COPYは標準的な部分取得の操作を開始します。
圧縮解析メソッド
圧縮されているべき所、されていない列が見つかった場合、これらの列の圧縮エンコーディングを決定する方法がいくつかあります。以下の通りです。
圧縮分析: Analyze Compression SQLコマンドは、既存のテーブルからデータをサンプリングし、COPY時の自動圧縮分析の処理と同様に、総当りな圧縮比較を行います。COPYとAnalyze Compressionでの主な違い:
- 排他的ロックが必要であり、実行中保持される
- テーブルの再構築はされない。推奨のみが返される
列エンコーディングユーティリティ: このユーティリティー(available in our amazon-redshift-utils project)はANALYZE COMPRESSIONステートメントに依存しています。ただし、推奨を返すだけでなく、推奨するエンコーディングでテーブルを再作成するために必要なSQLを作成します。自動的にそのSQLを実行するように構成することもできます。
固有の知識: 圧縮分析またはCOPY時の自動圧縮分析を利用する方法は、データのサンプリングとの比較に依存して推奨値が返却されます。このため、あなたが列のデータプロファイルの固有の知識、および今後の変化や変化の可能性を知っている場合は、アルゴリズムが予測したものより最適なエンコードを選択できる可能性があります。
次のステップ
すでに説明したように、ほとんどの場合、圧縮エンコードを使用してストレージのフットプリントを削減し、パフォーマンスを向上させることができます。 圧縮を必要とする列と適用するエンコーディングを特定する方法を理解したら、シンプルにテーブルを再構築してこれらの最適化を適用させられます。
第5部では、テーブル設計詳細ガイドの最終的な構成要素として、別なパフォーマンス向上方法であるテーブルデータ耐久性の使用方法について説明します。
Part 1: Preamble, Prerequisites, and Prioritization(序文、事前準備、優先順位付け)
Part 2: Distribution Styles and Distribution Keys(分散スタイルと分散キー)
Part 3: Compound and Interleaved Sort Keys(Compound と Interleaved ソートキー)
Part 4: Compression Encodings(圧縮エンコーディング)(本稿)
Part 5: Table Data Durability(テーブルデータの永続性)
著者について
Zach Christopherson はパロアルトを拠点とするAWSのシニアデータベースエンジニアです
彼は、全ての業界において、Amazon Redshift のユーザーが最適なパフォーマンスを得るためのワークロードをチューニングすることを支援しています。 Amazon Redshift サービスチームの一員として、彼は新しいサービスや既存のサービスの開発にも影響を与えており、貢献しています。休暇の際は妻のメアリーと一緒に新しいレストランにトライし、生まれたばかりの娘ソフィアの世話を楽しんでいます。
※日本語訳はSA益子(naoki014@)が担当しました。原文は Amazon Redshift Engineering’s Advanced Table Design Playbook: Compression Encodings
コメント