Amazon Redshift 新しい圧縮エンコーディング『AZ64』とLZO、ZSTDの徹底比較
これまでは主に高速なLZO、高圧縮なZSTDの2つ圧縮エンコーディングをノードタイプやワークロードに応じて選択していましたが、新たに追加されたAZ64は高速と高圧縮な特性を兼ね備えています。今回は新たに追加されたAZ64について検証したいと思います。
以下、本文の抜粋です。
高い圧縮率と改善されたクエリパフォーマンスの達成を目的として設計された独自の圧縮エンコーディングである AZ64 が利用可能になりました。革新的な AZ64 アルゴリズムは、データ値の小さなグループを効率的に圧縮し、SIMD 命令を活用してデータを並列処理します。このエンコードにより、ほとんどの場合、LZO および ZSTD エンコードに比べて大幅にストレージを節約でき、Amazon Redshift に保存されている数値および日付/時刻データの最適な解凍パフォーマンスが得られます。
AZ64 エンコーディングにより、LZO よりも一貫して優れたパフォーマンスと圧縮が実現されます。AZ64 エンコーディングは ZSTD と同等の圧縮機能を備えていますが、パフォーマンスは大幅に向上しています。テスト対象のワークロードでは、次の結果が確認できました。お客様のワークロードに対してどのようなメリットがあるかご確認ください。
- RAW エンコーディングと比較した場合、AZ64 は 25〜30% 高速で、60〜70% のストレージを節約できた。
- LZO エンコーディングと比較した場合、AZ64 は 40% 高速で、35% のストレージを節約できた。
- ZSTD エンコーディングと比較した場合、AZ64 は 70% 高速で、5〜10% のストレージを節約できた。
目次
新しい圧縮エンコーディング『AZ64』 とは
- AZ64 エンコード より引用
AZ64 は、高い圧縮率とクエリ処理能力の改善を実現するために設計された Amazon 独自の圧縮エンコードアルゴリズムです。Z64 アルゴリズムは、より小さなデータ値のグループを圧縮し、並列処理に SIMD (Single Instruction Multiple Data) 命令を使用します。AZ64 を使用すると、数値、日付、および時刻データ型のストレージを大幅に節約し、高いパフォーマンスを実現できます。次のデータ型の CREATE TABLE および ALTER TABLE ステートメントを使用して列を定義する場合、AZ64 を圧縮エンコードとして使用できます。
- SMALLINT
- INTEGER
- BIGINT
- DECIMAL
- DATE
- TIMESTAMP
- TIMESTAMPTZ
つまり、高い圧縮率とクエリ処理能力を両立したAmazon 独自の圧縮エンコードアルゴリズムです。対応したデータ型は、数値、日付、および時刻データ型となります。
テスト用データの作成
対応したデータ型は、数値、日付、および時刻データ型となりますので、INTEGER、DATE、TIMESTAMPの3種類のデータ型のデータを約6億レコード作成しました。
cmdb=> CREATE TABLE IF NOT EXISTS "cm_ishikawa_satoru"."lineorder_test" cmdb-> ( cmdb(> "lo_orderkey" INTEGER ENCODE raw cmdb(> ,"lo_orderdate" DATE ENCODE raw cmdb(> ,"lo_created" TIMESTAMP ENCODE raw cmdb(> ) cmdb-> ; CREATE TABLE Time: 452.855 ms cmdb=> INSERT INTO "cm_ishikawa_satoru"."lineorder_test" ( cmdb(> SELECT cmdb(> lo_orderkey, cmdb(> to_date(lo_orderdate::varchar, 'YYYYMMDD') as lo_orderdate, cmdb(> dateadd(s,ceil(random() * 315360000)::int,'2010-01-01') cmdb(> FROM "cm_ishikawa_satoru"."lineorder" cmdb(> ); INSERT 0 600037902 Time: 243289.360 ms (04:03.289) cmdb=> \x Expanded display is on. cmdb=> SELECT cmdb-> MIN(lo_orderkey) AS lo_orderkey_min, cmdb-> MAX(lo_orderkey) AS lo_orderkey_max, cmdb-> MIN(lo_orderdate) AS lo_orderdate_min, cmdb-> MAX(lo_orderdate) AS lo_orderdate_max, cmdb-> MIN(lo_created) AS lo_created_min, cmdb-> MAX(lo_created) AS lo_created_max cmdb-> FROM "cm_ishikawa_satoru"."lineorder_test" cmdb-> ; -[ RECORD 1 ]----+-------------------- lo_orderkey_min | 1 lo_orderkey_max | 600000000 lo_orderdate_min | 1992-01-01 lo_orderdate_max | 1998-08-02 lo_created_min | 2010-01-01 00:00:00 lo_created_max | 2019-12-30 00:00:00 Time: 11527.321 ms (00:11.527) cmdb=> \x Expanded display is off.
サンプルテーブルの作成
LZO、ZSTD、AZ64それぞれのテーブルを作成しました。
cmdb=> -- DROP TABLE "cm_ishikawa_satoru"."lineorder_test_lzo"; cmdb=> CREATE TABLE IF NOT EXISTS "cm_ishikawa_satoru"."lineorder_test_lzo" cmdb-> ( cmdb(> "lo_orderkey" INTEGER ENCODE lzo cmdb(> ,"lo_orderdate" DATE ENCODE lzo cmdb(> ,"lo_created" TIMESTAMP ENCODE lzo cmdb(> ) cmdb-> ; CREATE TABLE Time: 619.480 ms cmdb=> -- DROP TABLE "cm_ishikawa_satoru"."lineorder_test_zstd"; cmdb=> CREATE TABLE IF NOT EXISTS "cm_ishikawa_satoru"."lineorder_test_zstd" cmdb-> ( cmdb(> "lo_orderkey" INTEGER ENCODE zstd cmdb(> ,"lo_orderdate" DATE ENCODE zstd cmdb(> ,"lo_created" TIMESTAMP ENCODE zstd cmdb(> ) cmdb-> ; CREATE TABLE Time: 526.053 ms cmdb=> -- DROP TABLE "cm_ishikawa_satoru"."lineorder_test_az64"; cmdb=> CREATE TABLE IF NOT EXISTS "cm_ishikawa_satoru"."lineorder_test_az64" cmdb-> ( cmdb(> "lo_orderkey" INTEGER ENCODE az64 cmdb(> ,"lo_orderdate" DATE ENCODE az64 cmdb(> ,"lo_created" TIMESTAMP ENCODE az64 cmdb(> ) cmdb-> ; CREATE TABLE Time: 481.655 ms
データのディープコピー時間の計測
約6億レコード作成しました。 - LZO:134611.422 ms (02:14.611) 100%(基準) - ZSTD:131786.438 ms (02:11.786) 1.02143608%(2%向上)↑ - AZ64:111192.267 ms (01:51.192) 1.21061856%(21%向上)↑
cmdb=> INSERT INTO "lineorder_test_lzo" SELECT * FROM "lineorder_test"; INSERT 0 600037902 Time: 134611.422 ms (02:14.611) cmdb=> INSERT INTO "lineorder_test_zstd" SELECT * FROM "lineorder_test"; INSERT 0 600037902 Time: 131786.438 ms (02:11.786) cmdb=> INSERT INTO "lineorder_test_az64" SELECT * FROM "lineorder_test"; INSERT 0 600037902 Time: 111192.267 ms (01:51.192)
CPUの使用状況は、LZO、ZSTD、AZ64の順に以下のとおりです。やはり、AZ64がコピー時間もCPU使用率も少ないことが確認できます。
テーブルサイズの計測
- 非圧縮:14016MB 83.8%(16%低下)↓
- LZO:11752MB 100%(基準)
- ZSTD:10920MB 107.6%(7%向上)↑
- AZ64:10250MB 114.6%(14%向上)↑
cmdb=> SELECT "table", size FROM SVV_TABLE_INFO WHERE "schema" = 'cm_ishikawa_satoru' AND "table" = 'lineorder_test'; table | size ----------------+------- lineorder_test | 14016 (1 row) Time: 21297.637 ms (00:21.298) cmdb=> SELECT "table", size FROM SVV_TABLE_INFO WHERE "schema" = 'cm_ishikawa_satoru' AND "table" = 'lineorder_test_lzo'; table | size --------------------+------- lineorder_test_lzo | 11752 (1 row) Time: 1023.595 ms (00:01.024) cmdb=> SELECT "table", size FROM SVV_TABLE_INFO WHERE "schema" = 'cm_ishikawa_satoru' AND "table" = 'lineorder_test_zstd'; table | size ---------------------+------- lineorder_test_zstd | 10920 (1 row) Time: 1132.776 ms (00:01.133) cmdb=> SELECT "table", size FROM SVV_TABLE_INFO WHERE "schema" = 'cm_ishikawa_satoru' AND "table" = 'lineorder_test_az64'; table | size ---------------------+------- lineorder_test_az64 | 10250 (1 row) Time: 1161.759 ms (00:01.162)
CPUの使用状況は、非圧縮、LZO、ZSTD、AZ64の順に以下のとおりです。非圧縮はデータを展開するコストが無いので最もCPU使用率が少ない結果になりましたが、非圧縮以外ではAZ64がコピー時間もCPU使用率も少ないことが確認できます。
クエリの実行時間の計測
データブロックの展開コストが生じる集計クエリを実行して計測しています。
- 非圧縮:63398.593 ms (01:03.399) 133.9%↑
- LZO:84890.756 ms (01:24.891) 100%(基準)
- ZSTD:84995.011 ms (01:24.995) 99.8%↓
- AZ64:81564.053 ms (01:21.564) 104.0%↑
cmdb=> SELECT count(*) FROM ( cmdb(> SELECT lo_orderkey, lo_orderdate, count(*) FROM "lineorder_test" GROUP BY 1,2 cmdb(> ); count ----------- 150000000 (1 row) Time: 63398.593 ms (01:03.399) cmdb=> SELECT count(*) FROM ( cmdb(> SELECT lo_orderkey, lo_orderdate, count(*) FROM "lineorder_test_lzo" GROUP BY 1,2 cmdb(> ); count ----------- 150000000 (1 row) Time: 84890.756 ms (01:24.891) cmdb=> SELECT count(*) FROM ( cmdb(> SELECT lo_orderkey, lo_orderdate, count(*) FROM "lineorder_test_zstd" GROUP BY 1,2 cmdb(> ); count ----------- 150000000 (1 row) Time: 84995.011 ms (01:24.995) cmdb=> SELECT count(*) FROM ( cmdb(> SELECT lo_orderkey, lo_orderdate, count(*) FROM "lineorder_test_az64" GROUP BY 1,2 cmdb(> ); count ----------- 150000000 (1 row) Time: 81564.053 ms (01:21.564)
まとめ
INTEGER型、DATE型、TIMESTAMP型に対して圧縮アルゴリズム『AZ64』との検証の結果を表にまとめました。
ディープコピー時間 | テーブルサイズ | クエリの実行時間 | |
---|---|---|---|
非圧縮 | ー | 14016MB 83.8%(16%低下) ↓ |
63398.593 ms (01:03.399) 133.9% ↑ |
LZO | 134611.422 ms (02:14.611) 100%(基準) |
11752MB 100%(基準) |
84890.756 ms (01:24.891) 100%(基準) |
ZSTD | 131786.438 ms (02:11.786) 102.1%(2%向上) ↑ |
10920MB 107.6%(7%向上) ↑ |
84995.011 ms (01:24.995) 99.8% ↓ |
AZ64 | 111192.267 ms (01:51.192) 121.1%(21%向上) ↑ |
10250MB 114.6%(14%向上) ↑ |
81564.053 ms (01:21.564) 104.0% ↑ |
今回の検証の結果、AZ64はINTEGER型、DATE型、TIMESTAMP型おいて、高い圧縮率とクエリ処理能力を両立した圧縮エンコードアルゴリズムであることが証明されました。但し、サポートしているデータ型が数値型の一部とやDATE型とTIMESTAMP型に限られているため、その他のデータ型は他の圧縮アルゴリズムを選択することになります。今回の検証では文字列型が対象に含まれなかったのですが、LZOは高い圧縮率とクエリ処理能力のバランスが良いので、必ずしもZSTDがLZOよりも良いとは限りません。
圧縮アルゴリズムを分析するANALYZE COMPRESSION
を実行した所、執筆時点(2019/11/10)では、残念ながらAZ64を提案されないようです。
cmdb=> ANALYZE COMPRESSION "lineorder_test"; Table | Column | Encoding | Est_reduction_pct ----------------+--------------+----------+------------------- lineorder_test | lo_orderkey | zstd | 7.17 lineorder_test | lo_orderdate | zstd | 99.91 lineorder_test | lo_created | zstd | 17.03 (3 rows) Time: 15954.469 ms (00:15.954)
データ型と圧縮アルゴリズムの対応状況は以下のとおりです。上記の検証結果と以下の対応状況を参考に圧縮エンコーディングアルゴリズムを選択すると良いでしょう。
データ型 | 別名 | LZO | ZSTD | AZ64 |
---|---|---|---|---|
SMALLINT | INT2 | ○ | ○ | ○ |
INTEGER | INT、INT4 | ○ | ○ | ○ |
BIGINT | INT8 | ○ | ○ | ○ |
DECIMAL | NUMERIC | ○ | ○ | ○ |
REAL | FLOAT4 | ☓ | ○ | ☓ |
DOUBLE PRECISION | FLOAT8、FLOAT | ☓ | ○ | ☓ |
BOOLEAN | BOOL | ☓ | ○ | ☓ |
CHAR | CHARACTER、NCHAR、BPCHAR | ○ | ○ | ☓ |
VARCHAR | CHARACTER VARYING、NVARCHAR、TEXT | ○ | ○ | ☓ |
DATE | ○ | ○ | ○ | |
TIMESTAMP | TIMESTAMP WITHOUT TIME ZONE | ○ | ○ | ○ |
TIMESTAMPTZ | TIMESTAMP WITH TIME ZONE | ○ | ○ | ○ |