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

2017.02.10

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

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

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

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