Amazon Redshift 新しい圧縮エンコーディング『AZ64』とLZO、ZSTDの徹底比較

2019.11.11

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

これまでは主に高速な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 は、高い圧縮率とクエリ処理能力の改善を実現するために設計された 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