この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
COPY/UNLOADコマンドが、BZIP2フォーマットで圧縮されたデータをサポートし、Amazon Redshiftへのデータロード/アンロード時に利用できるようになりました。(Cluster Version: 1.0.1034)
これまでサポートされていたGZIPとLZOP(LZOファイル)に対して、BZIP2が優れている点はズバリ圧縮率の高さですが、圧縮・展開に要する負荷が気になるところです。今回はGZIPとLZOP、BZIP2を比較検証し、効果的な利用方法をご紹介したいと思います。
BZIP2とは
BZIP2は GZIPのハフマン符号にブロックソート法(バロウズ-ホイラー変換)と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ファイル形式を選択できるようになりました。実際の導入・検討においては、ロード対象のテーブルに、列圧縮、ソートキーの要否も含めたた時間を計測して導入をご検討ください。