Amazon Redshift: 【新機能】列圧縮の圧縮エンコードとして、ZSTDが追加されました

Amazon Redshift

はじめに

好物はインフラとフロントエンドのかじわらゆたかです。

Redshiftの列の圧縮エンコードとしてZSTDが追加になりました。

Amazon Redshift now supports the Zstandard high data compression encoding and two new aggregate functions

ZSTDはFacebook が開発を行っている圧縮アルゴリズムのようです。
facebook/zstd: Zstandard - Fast real-time compression algorithm

一点勘違いしそうなのが、copyコマンドの取り込み形式の追加ではなく、列形式の圧縮アルゴリズムの追加となります。 そのためZSTD形式でのファイルを用意するとかそういうことは必要ではなく、テーブル作成時の圧縮エンコードでZSTDを指定することで適用することができます。

今回性能検証のため、AWS のドキュメントのテーブル設計のチューニングのチュートリアルに則ってパフォーマンス等を確認していきます。

チュートリアル: テーブル設計のチューニング - Amazon Redshift

今回の検証については、以下の構成で行っております。

  • Node Type: dw2.large
  • Nodes: 2

テストデータセットの作成

テーブル作成

チュートリアルではすべて圧縮無しで作成していますが、今回は圧縮なしとZSTDで比較をしたいので、ZSTDを圧縮エンコードとしたテーブルを作成します。 ZSTD版のクエリは以下になります。

CREATE TABLE part_ZSTD 
(
  p_partkey     INTEGER NOT NULL encode ZSTD,
  p_name        VARCHAR(22) NOT NULL encode ZSTD,
  p_mfgr        VARCHAR(6) NOT NULL encode ZSTD,
  p_category    VARCHAR(7) NOT NULL encode ZSTD,
  p_brand1      VARCHAR(9) NOT NULL encode ZSTD,
  p_color       VARCHAR(11) NOT NULL encode ZSTD,
  p_type        VARCHAR(25) NOT NULL encode ZSTD,
  p_size        INTEGER NOT NULL encode ZSTD,
  p_container   VARCHAR(10) NOT NULL encode ZSTD
);

CREATE TABLE supplier_ZSTD 
(
  s_suppkey   INTEGER NOT NULL encode ZSTD,
  s_name      VARCHAR(25) NOT NULL encode ZSTD,
  s_address   VARCHAR(25) NOT NULL encode ZSTD,
  s_city      VARCHAR(10) NOT NULL encode ZSTD,
  s_nation    VARCHAR(15) NOT NULL encode ZSTD,
  s_region    VARCHAR(12) NOT NULL encode ZSTD,
  s_phone     VARCHAR(15) NOT NULL encode ZSTD
);

CREATE TABLE dwdate_ZSTD 
(
  d_datekey            INTEGER NOT NULL encode ZSTD,
  d_date               VARCHAR(19) NOT NULL encode ZSTD,
  d_dayofweek          VARCHAR(10) NOT NULL encode ZSTD,
  d_month              VARCHAR(10) NOT NULL encode ZSTD,
  d_year               INTEGER NOT NULL encode ZSTD,
  d_yearmonthnum       INTEGER NOT NULL encode ZSTD,
  d_yearmonth          VARCHAR(8) NOT NULL encode ZSTD,
  d_daynuminweek       INTEGER NOT NULL encode ZSTD,
  d_daynuminmonth      INTEGER NOT NULL encode ZSTD,
  d_daynuminyear       INTEGER NOT NULL encode ZSTD,
  d_monthnuminyear     INTEGER NOT NULL encode ZSTD,
  d_weeknuminyear      INTEGER NOT NULL encode ZSTD,
  d_sellingseason      VARCHAR(13) NOT NULL encode ZSTD,
  d_lastdayinweekfl    VARCHAR(1) NOT NULL encode ZSTD,
  d_lastdayinmonthfl   VARCHAR(1) NOT NULL encode ZSTD,
  d_holidayfl          VARCHAR(1) NOT NULL encode ZSTD,
  d_weekdayfl          VARCHAR(1) NOT NULL encode ZSTD
);
CREATE TABLE lineorder_ZSTD 
(
  lo_orderkey          INTEGER NOT NULL encode ZSTD,
  lo_linenumber        INTEGER NOT NULL encode ZSTD,
  lo_custkey           INTEGER NOT NULL encode ZSTD,
  lo_partkey           INTEGER NOT NULL encode ZSTD,
  lo_suppkey           INTEGER NOT NULL encode ZSTD,
  lo_orderdate         INTEGER NOT NULL encode ZSTD,
  lo_orderpriority     VARCHAR(15) NOT NULL encode ZSTD,
  lo_shippriority      VARCHAR(1) NOT NULL encode ZSTD,
  lo_quantity          INTEGER NOT NULL encode ZSTD,
  lo_extendedprice     INTEGER NOT NULL encode ZSTD,
  lo_ordertotalprice   INTEGER NOT NULL encode ZSTD,
  lo_discount          INTEGER NOT NULL encode ZSTD,
  lo_revenue           INTEGER NOT NULL encode ZSTD,
  lo_supplycost        INTEGER NOT NULL encode ZSTD,
  lo_tax               INTEGER NOT NULL encode ZSTD,
  lo_commitdate        INTEGER NOT NULL encode ZSTD,
  lo_shipmode          VARCHAR(10) NOT NULL encode ZSTD
);

データロード

チュートリアルでは、AccessKeyとSecretAccessKeyを用いた形になっていますが、IAM Roleからも当該リソースはアクセス可能なため、 IAM Roleで当該リソースへのアクセスを行なってCopyコマンドを実行しました。 lineorderは全件取り込むと無圧縮で50Gほどになるため、一部のみ取り込んでいます。

copy customer from 's3://awssampledbuswest2/ssbgz/customer' 
CREDENTIALS 'aws_iam_role=arn:aws:iam::nnnnnnnnnnnn:role/redshift-role-mmmmmmmmm'
gzip compupdate off region 'us-west-2';

copy dwdate from 's3://awssampledbuswest2/ssbgz/dwdate' 
credentials 'aws_iam_role=arn:aws:iam::nnnnnnnnnnnn:role/redshift-role-mmmmmmmmm'
gzip compupdate off region 'us-west-2';

copy lineorder from 's3://awssampledbuswest2/ssbgz/lineorder0000_part_00.gz' 
credentials 'aws_iam_role=arn:aws:iam::nnnnnnnnnnnn:role/redshift-role-mmmmmmmmm'
gzip compupdate off region 'us-west-2';

copy part from 's3://awssampledbuswest2/ssbgz/part' 
credentials 'aws_iam_role=arn:aws:iam::nnnnnnnnnnnn:role/redshift-role-mmmmmmmmm'
gzip compupdate off region 'us-west-2';

copy supplier from 's3://awssampledbuswest2/ssbgz/supplier' 
credentials 'aws_iam_role=arn:aws:iam::nnnnnnnnnnnn:role/redshift-role-mmmmmmmmm'
gzip compupdate off region 'us-west-2';

Copyコマンド実行時間については以下のようになりました。

圧縮エンコード 実行時間
圧縮なし 5 min 16 sec
ZSTD 5min 42sec

Copyの時間は圧縮を実行したテーブルに対して5%ほどのCopy時間が増えています。 Copyについては圧縮の有無でのパフォーマンスの劣化等はそれほど気にしなくても良さそうです。

次にストレージの使用量を調べてみます。

table mbytes
customer 368
customer_zstd 140
dwdate 80
dwdate_zstd 80
lineorder 6404
lineorder_zstd 3240
supplier 124
supplier_zstd 60

テーブルのストレージ単位はMbyteになっています。 dwdateテーブル以外は圧縮でテーブルの容量がかなり削減できていることがわかります。

クエリパフォーマンス(ソートキー・分散スタイル未設定)

上記の状態でのクエリのパフォーマンスを測定してみたいと思います。 測定方法はチュートリアルのステップ 2: システムパフォーマンスをテストしてベースラインを確定するを元におこないます。

まずは無圧縮のテーブルに対して、実行した結果は以下のようになりました。

query milli second
Query1 606
Query2 3266
Query3 2974

次にZSTDで全カラムを圧縮したテーブルに対して行なってみました。

query milli second
Query1 3023
Query2 4565
Query3 4813

特にQuery1の時間が無圧縮だったときに比べて5倍ほどの差がついています。 推測ではありますが、格納しているレコード数が多く、また全カラムを圧縮しているため、 解凍に時間がかかったため、このような結果になったのではと推測しております。

さすがにこれでは優位性がストレージ容量だけになってしまうので、もう少し突っ込んでみたいと思います。

クエリパフォーマンス(ソートキー・分散スタイル設定済み)

比較対象としては以下になります。

まずはCopyコマンドの実行結果から

圧縮エンコード 実行時間
チュートリアル 8 min 34 sec
ZSTD + Sort + 分散 6min 39sec

チュートリアル版の方が処理時間がかかっていますが、これは初回Copy時に圧縮タイプを決めていたりするのが原因かなと思っています。

ストレージの使用量について調べてみます。

table mbytes
customer_sort 302
customer_zstd_sort 274
dwdate_sort 80
dwdate_zstd_sort 80
lineorder_sort 3501
lineorder_zstd_sort 3393
part_sort 112
part_zstd_sort 116
supplier_sort 118
supplier_zstd_sort 108

*_sortとなっているテーブルがチュートリアルに基いて作成したテーブル、 *_zstd_sortとなっているのがソートキーと分散スタイルを設定し、それソートキー以外はZSTD形式にて圧縮したテーブルとなります。

ZSTDで圧縮かけたほうが最大で1割くらい自動で決められたエンコードよりデータ容量が少なくなっていることがわかります。

最後にクエリの性能を調べてみたいと思います。

チュートリアル版

query milli second
Query1 258
Query2 3305
Query3 783

ZSTD + ソートキー + 分散スタイル

query milli second
Query1 523
Query2 3991
Query3 951

実行するクエリによっては1~2割程度実行時間に差が出た形になりますが、一番差があるところがは2倍差がついていたりします。 実際に投入されたデータに基いて決められた圧縮エンコードが有利といえばそれまでですが、 何も考えずに設定したZSTDとの差があまり無いのというの点は評価できるのではと思います。 圧縮エンコーディングについては、見直すこと前提でひとまずZSTDとするといった使い方ができるのかなと思います。

結論

新しい圧縮エンコーディングであるZSTDについて調べてみました。

絶対にZSTDだよ!というほど優位性のある結果が得れなかったのは残念ですが、 一括で設定した場合においても性能がそんなにひどく劣化するといった事が無い事が確認できました。

実際にどういった用途に用いれるのかは今後検討していく必要があるのかなと言う感じです。