Redshift SpectrumでのParquetのMIN/MAXプルーニング
Redshift SpectrumではS3上に置かれたファイルをクエリすることができる機能です。
サポートしているファイルフォーマットはいくつかありますが、有名なフォーマットとしてParquetがあります。
Parquetではカラムごとに、いくつかのグループでまとまって管理が行われ、そのグループごとに最小値、最大値の統計情報を持っています。Redshift Spectrumではその統計情報を確認することで、不要なグループを読み飛ばすMIN/MAXプルーニングを行うことができます。
データの準備
Redshiftに格納されているTPC-Hのlineitem表からS3にParquetのデータを2種類作成します。
- lineitem表のデータをそのままS3に出力するクエリ
CREATE EXTERNAL TABLE lineitem_spectrum
STORED AS parquet
LOCATION 's3://my-bucket/lineitem-spectrum/'
AS (SELECT * FROM lineitem)
- lineitem表のl_partkeyでソートしてS3に出力するクエリ
CREATE EXTERNAL TABLE lineitem_sort_spectrum
STORED AS parquet
LOCATION 's3://my-bucket/lineitem-sort-spectrum/'
AS (SELECT * FROM lineitem ORDER BY l_partkey)
これでS3上に2つのParquet形式のデータが出力されました。
データの確認
Parquetファイルはparquet-toolsというコマンドでファイル内の統計情報などを確認することができます。
作成した2つのParquetデータについてparquet-toolsを使って内容を確認します。
- lineitem表のデータをそのままS3に出力したデータの場合
# parquet-tools meta 20220424_223803_666831_1957505_0000_part_00.parquet
row group 1: RC:1117179 TS:29948957 OFFSET:4
--------------------------------------------------------------------------------
l_orderkey: INT64 SNAPPY DO:4 FPO:453763 SZ:2787792/3092728/1.11 VC:1117179 ENC:RLE,PLAIN_DICTIONARY,PLAIN ST:[min: 197, max: 5999910, num_nulls: 0]
l_partkey: INT64 SNAPPY DO:2787891 FPO:3406779 SZ:3480255/5024003/1.44 VC:1117179 ENC:RLE,PLAIN_DICTIONARY,PLAIN ST:[min: 1, max: 200000, num_nulls: 0]
...
row group 2: RC:385449 TS:10091968 OFFSET:29950219
--------------------------------------------------------------------------------
l_orderkey: INT64 SNAPPY DO:29950219 FPO:30255537 SZ:942922/1253641/1.33 VC:385449 ENC:RLE,PLAIN_DICTIONARY,PLAIN ST:[min: 197, max: 5999586, num_nulls: 0]
l_partkey: INT64 SNAPPY DO:30893238 FPO:31256452 SZ:1171679/1435303/1.22 VC:385449 ENC:RLE,PLAIN_DICTIONARY,PLAIN ST:[min: 2, max: 199999, num_nulls: 0]
...
グループであるrow group
単位で統計情報が表示されています。l_partkey
に関してはrow group 1
はmin: 1, max: 200000
であり、row group 2
はmin: 2, max: 199999
なのでほぼ均等に同じようなデータが含まれていることが確認できます。
- lineitem表をl_partkeyでソートしてS3に出力したデータの場合
# parquet-tools meta 20220512_234059_265253_2462149_0000_part_00.parquet
row group 1: RC:1483366 TS:31228049 OFFSET:4
--------------------------------------------------------------------------------
l_orderkey: INT64 SNAPPY DO:4 FPO:475158 SZ:3629214/3905445/1.08 VC:1483366 ENC:RLE,PLAIN_DICTIONARY,PLAIN ST:[min: 197, max: 5999910, num_nulls: 0]
l_partkey: INT64 SNAPPY DO:3629313 FPO:4153852 SZ:1670375/4615475/2.76 VC:1483366 ENC:RLE,PLAIN_DICTIONARY,PLAIN ST:[min: 1, max: 197431, num_nulls: 0]
...
row group 2: RC:19262 TS:460646 OFFSET:31229299
--------------------------------------------------------------------------------
l_orderkey: INT64 SNAPPY DO:31229299 FPO:31253144 SZ:55213/68978/1.25 VC:19262 ENC:RLE,PLAIN_DICTIONARY,PLAIN ST:[min: 896, max: 5998243, num_nulls: 0]
l_partkey: INT64 SNAPPY DO:31284608 FPO:31293372 SZ:19103/30147/1.58 VC:19262 ENC:RLE,PLAIN_DICTIONARY,PLAIN ST:[min: 197431, max: 200000, num_nulls: 0]
...
l_partkey
に関してはrow group 1
はmin: 1, max: 197431
、row group 2
はmin: 197431, max: 200000
となっています。l_partkey
でソートして出力したため、それぞれのグループで担当する値の範囲が異なっています。
MIN/MAXプルーニングの効果を確認する
S3に出力されたlineitemのデータは600万件となっています。
このデータに対して以下のクエリを実行しMIN/MAXプルーニングの効果を確認します。
SELECT * FROM lineitem_spectrum WHERE l_partkey > 197431
SELECT * FROM lineitem_sort_spectrum WHERE l_partkey > 197431
結果は以下となります。
lineitem_spectrum | lineitem_sort_spectrum |
---|---|
1842ms | 890ms |
l_partkey
でソートされているテーブル(lineitem_sort_spectrum)の方がMIN/MAXプルーニングにより不要なグループ(row group 1
)を読み飛ばすことで2倍以上高速になることがわかりました。