【新機能】Redshift COPY/UNLOADのBZIP2ファイル対応を試してみました

2016.02.21

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

COPY/UNLOADコマンドが、BZIP2フォーマットで圧縮されたデータをサポートし、Amazon Redshiftへのデータロード/アンロード時に利用できるようになりました。(Cluster Version: 1.0.1034)

これまでサポートされていたGZIPとLZOP(LZOファイル)に対して、BZIP2が優れている点はズバリ圧縮率の高さですが、圧縮・展開に要する負荷が気になるところです。今回はGZIPとLZOP、BZIP2を比較検証し、効果的な利用方法をご紹介したいと思います。

COPYでのBZIP2ファイル対応(2015/12/06)

BZIP2でのUNLOADが追加(2016/02/09)

BZIP2とは

BZIP2GZIPハフマン符号にブロックソート法(バロウズ-ホイラー変換)とMTF (Move-To-Front) 法によって圧縮を効率化したデータ圧縮プログラムです。GZIPと比較して圧縮・展開にデータの入れ替えが発生する点が大きく異なります。 bzip2コマンドはgzipコマンドのオプションとほとんど同じですが、データ圧縮方式が異なるのでストリーム圧縮などは不向きです。BZIP2は、ネットワーク経由で配布される比較的サイズの大きなファイルの圧縮に用いられることが多く、Linuxカーネルのソースコードの圧縮に利用されています。

ファイル時間・圧縮率の比較

COPYを実行する前に、GZIP、LZOP、BZIP2、のファイルの作成に要する時間、圧縮率を確認します。(m4.large、30GB(90IOPS))

$ time gzip  -c lineorder0000_part_00 > lineorder0000_part_00.gz
real    14m8.876s
user    11m54.256s
sys 0m4.392s

$ time lzop  -c lineorder0000_part_00 > lineorder0000_part_00.lzo
real    4m53.938s
user    0m41.196s
sys 0m4.760s

$ time bzip2 -c lineorder0000_part_00 > lineorder0000_part_00.bz2
real    15m25.393s
user    13m6.572s
sys 0m3.884s

$ ll
-rw-rw-r-- 1 ec2-user ec2-user 7578653024  2月 10 00:41 lineorder0000_part_00.txt
-rw-rw-r-- 1 ec2-user ec2-user 2995053367  2月 10 00:56 lineorder0000_part_00.gz
-rw-rw-r-- 1 ec2-user ec2-user 4855212994  2月 10 01:01 lineorder0000_part_00.lzo
-rw-rw-r-- 1 ec2-user ec2-user 2431302024  2月 10 01:15 lineorder0000_part_00.bz2

BZIP2ファイルとGZIPファイルを比較すると、19%コンパクトになり、圧縮時間は9%程余計にかかりました。

ファイル名 圧縮時間 ファイルサイズ
lineorder0000_part_00.txt - 7227MB (100%)
lineorder0000_part_00.gz 14分 8.876秒 2856MB (39.5%)
lineorder0000_part_00.lzo 4分 53.938秒 4630MB (64.0%)
lineorder0000_part_00.bz2 15分 25.393秒 2318MB (32.0%)

なお、ファイルの展開に要する時間は以下のとおりです。

$ time gzip  -d lineorder0000_part_00.gz
real    4m9.819s
user    1m10.896s
sys 0m5.892s

$ time lzop  -d lineorder0000_part_00.lzo
real    3m53.687s
user    0m28.856s
sys 0m5.696s

$ time bzip2 -d lineorder0000_part_00.bz2
real    6m37.530s
user    6m18.076s
sys 0m7.468s
ファイル名 処理時間
lineorder0000_part_00.gz 4分 9.819秒
lineorder0000_part_00.lzo 3分 53.687秒
lineorder0000_part_00.bz2 6分 37.530秒

COPYコマンド処理時間の比較

比較は、非圧縮、GZIP、LZO、BZIP2の4種類のロード時間を比較します。ロード時間の計測が目的なので、ロード対象のテーブルは列圧縮やソートキーの指定していません。Redshiftクラスタはdc1.largeのシングルノードクラスタ構成です。

db=# COPY public.lineorder FROM 's3://cm-test/data/lineorder0000_part_00.txt'
db-# CREDENTIALS 'aws_access_key_id=<aws_access_key_id>;aws_secret_access_key=<aws_secret_access_key>'
db-# COMPUPDATE OFF
db-# ;
INFO:  Load into table 'lineorder' completed, 75004738 record(s) loaded successfully.
COPY
時間: 239362.878 ms

db=# COPY public.lineorder_gzip FROM 's3://cm-test/data/lineorder0000_part_00.gz'
db-# CREDENTIALS 'aws_access_key_id=<aws_access_key_id>;aws_secret_access_key=<aws_secret_access_key>'
db-# COMPUPDATE OFF
db-# GZIP;
INFO:  Load into table 'lineorder_gzip' completed, 75004738 record(s) loaded successfully.
COPY
時間: 318738.658 ms

db=# COPY public.lineorder_lzop FROM 's3://cm-test/data/lineorder0000_part_00.lzo'
db-# CREDENTIALS 'aws_access_key_id=<aws_access_key_id>;aws_secret_access_key=<aws_secret_access_key>'
db-# COMPUPDATE OFF
db-# LZOP;
INFO:  Load into table 'lineorder_lzop' completed, 75004738 record(s) loaded successfully.
COPY
時間: 310145.333 ms

db=# COPY public.lineorder_bzip2 FROM 's3://cm-test/data/lineorder0000_part_00.bz2'
db-# CREDENTIALS 'aws_access_key_id=<aws_access_key_id>;aws_secret_access_key=<aws_secret_access_key>'
db-# COMPUPDATE OFF
db-# BZIP2;
INFO:  Load into table 'lineorder_bzip2' completed, 75004738 record(s) loaded successfully.
COPY
時間: 652142.929 ms

BZIP2ファイルのロード時間はGZIPファイルよりも倍以上に時間がかかりました。

ファイル名 ロード時間
lineorder0000_part_00.txt 3分 59.362秒
lineorder0000_part_00.gz 5分 18.738秒
lineorder0000_part_00.lzo 5分 10.145秒
lineorder0000_part_00.bz2 10分 52.142秒

UNLOADコマンド処理時間の比較

比較対象や条件は、COPYコマンド処理時間の比較と同様です。

db=> \timing
Timing is on.

db=> UNLOAD ('select * from public.lineorder') TO 's3://cm-test/data/unload_lineorder0000_part_00.txt'
db-> CREDENTIALS 'aws_access_key_id=<aws_access_key_id>;aws_secret_access_key=<aws_secret_access_key>'
db-> ;
UNLOAD
Time: 223529.049 ms

db=> UNLOAD ('select * from public.lineorder') TO 's3://cm-test/data/unload_lineorder0000_part_00.gz'
db-> CREDENTIALS 'aws_access_key_id=<aws_access_key_id>;aws_secret_access_key=<aws_secret_access_key>'
db-> GZIP
db-> ;
UNLOAD
Time: 176481.783 ms

db=> UNLOAD ('select * from public.lineorder') TO 's3://cm-test/data/unload_lineorder0000_part_00.lzo'
db-> CREDENTIALS 'aws_access_key_id=<aws_access_key_id>;aws_secret_access_key=<aws_secret_access_key>'
db-> LZOP
db-> ;
ERROR:  syntax error at or near "LZOP"
LINE 3: LZOP
        ^
Time: 183.456 ms

db=> UNLOAD ('select * from public.lineorder') TO 's3://cm-test/data/unload_lineorder0000_part_00.bz2'
db-> CREDENTIALS 'aws_access_key_id=<aws_access_key_id>;aws_secret_access_key=<aws_secret_access_key>'
db-> BZIP2
db-> ;
UNLOAD
Time: 413365.101 ms

データファイルを確認します。データのアンロードはスライスごとにファイルが出力されるので4つのファイルに分かれています。

$ aws s3 ls s3://cm-test/data/ 
2016-02-21 02:20:49  567825401 unload_lineorder0000_part_00.bz20000_part_00.bz2
2016-02-21 02:20:49  569355417 unload_lineorder0000_part_00.bz20001_part_00.bz2
2016-02-21 02:20:49  568011425 unload_lineorder0000_part_00.bz20002_part_00.bz2
2016-02-21 02:20:49  568974229 unload_lineorder0000_part_00.bz20003_part_00.bz2
2016-02-21 02:15:01  806096803 unload_lineorder0000_part_00.gz0000_part_00.gz
2016-02-21 02:15:01  808192504 unload_lineorder0000_part_00.gz0001_part_00.gz
2016-02-21 02:15:01  806378596 unload_lineorder0000_part_00.gz0002_part_00.gz
2016-02-21 02:15:01  807741865 unload_lineorder0000_part_00.gz0003_part_00.gz
2016-02-21 02:09:14 1892348369 unload_lineorder0000_part_00.txt0000_part_00
2016-02-21 02:09:14 1897227075 unload_lineorder0000_part_00.txt0001_part_00
2016-02-21 02:09:15 1892914739 unload_lineorder0000_part_00.txt0002_part_00
2016-02-21 02:09:15 1896162841 unload_lineorder0000_part_00.txt0003_part_00

アンロード時間は、BZIP2と比較するとGZIPの2.34倍です。非圧縮よりもGZIP圧縮の方がアンロード時間が短いのは興味深いです。恐らく、圧縮の処理時間よりもS3への出力時間のほうが余計にかかってしまったのではないかと考えられます。 なお、LZOのUNLOADはサポートしていませんので、エラーで終了となりました。 出力したファイルサイズに着目すると、Redshiftのアンロードファイルのほうが圧縮率が高いようです。これはRedshift内部で実行時の圧縮オプションは、bzip2コマンドやgzipコマンドのデフォルトの圧縮率よりも高い設定になっているからと考えられます。

ファイル名 アンロード時間 ファイルサイズ
unload_lineorder0000_part_00.txt 3分 43.529秒 7227MB
unload_lineorder0000_part_00.gz 2分 56.481秒 3079MB
unload_lineorder0000_part_00.lzo
unload_lineorder0000_part_00.bz2 6分 53.365秒 2169MB

検証の結果

今回の検証の結果では、データファイルの圧縮時間(GZIPと比較して10%増)に対して高い圧縮率(19%圧縮)であることが確認できました。この結果はデータソースを作成するEC2のインスタンスタイプやEBSのIO性能(IOPS)に依存します。上記の実行結果では、ユーザー空間のCPU利用時間(user)も掲載していますの合わせて参考にしてください。

データのロードではGZIPと比較して2倍、LZOと比較して3倍でした。アンロードはGZIPと比較して2.3倍です。EC2上での圧縮ファイルの圧縮・展開ではこれほどの差が見られませんでしたので、Redshiftでのファイル展開のコストは想定以上に大きい印象です。

今回はデータソースとなるファイルの圧縮率の違いによるロード・アンロードを計測することが目的なので、利用したテーブルは列圧縮やソートキーの指定をしていません。

最後に

データの圧縮・展開は、GZIPと2倍以上ですが、データファイルをよりコンパクトに保存したい時には有効といえます。オンプレやDRサイト間でネットワーク介して大きなデータをやり取りするユースケースは有効でしょう。一方、データのロード・アンロードは倍以上の時間を要しますので、限られた時間でデータをロード・アンロードするようなユースケースには不向きと考えられます。

データソースとしてBZIP2ファイル形式を選択できるようになりました。実際の導入・検討においては、ロード対象のテーブルに、列圧縮、ソートキーの要否も含めたた時間を計測して導入をご検討ください。