AWS Athenaで列試行のデータストレージ形式Parquetのデータを扱ってみた
Contents
Parquet(パーケイ)
以前の記事でs3上のデータに対して簡単にSQLを発行する事が出来るAWSのサービスAthenaを試してみた。
その際はCSV形式のファイルに対してSQLを発行したのだがAthenaはスキャンしたデータ量に応じて課金される料金体系(1TB=5USD)になっている。
CSVファイルの場合は1列だけのselectであったとしても同じ行の他の項目もスキャンしてしまうが、Parquet(パーケイ)はファイルサイズが圧縮される上に特定の列だけを取得するようなSQLではスキャン量が減るという事なのでCSVと比較してみたいと思う。
試した環境
試した環境は以下の通り。
OS | Windows10 Home 64Bit |
パソコン | DELL G7 15 |
ブラウザ | Google Chrome |
Python | Python 3.6.8 :: Anacond |
用意したデータ
"tempkeyindex","clientid","humicheck","humidity","locationid","locationname","max_humi","max_temp","min_humi","min_temp","status","tempcheck","tempdatetime","temperature"
"2020-07-24T12:30:01temperature0001","temperature0001","OK",58.7,"H1F0002","倉庫1F-001",70,40,10,5,"0","OK","2020-07-24T12:30:01",10.2
・
・
・
・
あまり小さいサイズのファイルでも誤差が出ると思うので、62,665行でファイルサイズが8,654,524ByteのCSVファイルを用意した。
Parquet形式に変換
PythonのプログラムでCSVからParquetに変換する。
必要モジュールのインストール
Apache Arrow(PyArrow)をAnacondaプロンプトから以下のコマンドでインストールする。
pip install pyarrow
バージョン0.17.1のpyarrowがインストールされた。
プログラム
# -*- coding: utf-8 -*-
"""
Created on Sat Jul 18 22:02:04 2020
CSV to Parquet
@author: Souichirou Kikuchi
"""
import pandas as pd
import pyarrow as pa
import pyarrow.parquet as pq
df = pd.read_csv('./temp_iot.csv')
table = pa.Table.from_pandas(df)
pq.write_table(table, './temp_iot.parquet')
temp_iot.csvファイルを読み込んでParquet形式に変換してtemp_iot.parquetに出力するだけの単純なプログラム。
temp_iot.parquetのファイルサイズは218,271Byteで変換しただけで約1/40のファイルサイズになった。
AWS s3にアップロード
CSVとParquetをそれぞれs3にアップロードする。
- s3://temp-humi/data/temp_iot.csv(8,654,524Byte)
- s3://temp-humi/pqdata/temp_iot.parquet(218,271Byte)
Create Table
s3上のファイルに対してテーブル定義を行う
CSVのテーブル定義は以前の記事を参照。
AWSのメニューのサービス一覧からAthenaを呼び出してParquetファイルに対してテーブル作成クエリーを実行する。
CREATE EXTERNAL TABLE IF NOT EXISTS default.temp_humi_pq_table (
tempkeyindex string,
clientid string,
humicheck string,
humidity double,
locationid string,
locationname string,
max_humi double,
max_temp double,
min_humi double,
min_temp double,
status string,
tempcheck string,
tempdatetime string,
temperature double
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
WITH SERDEPROPERTIES (
'serialization.format' = '1'
) LOCATION 's3://temp-humi/pqdata/';
temp_humi_pq_tableテーブルが作成された。
ここでちょっとハマったのが浮動小数点の属性の指定の仕方。
当初floatを指定していたのだがcreate tableの時はエラーにならずselect時にエラーになってしまっていた。
doubleを指定したら問題なくselectも出来るようになった。
SQLの実行
それぞれのテーブルに対してSQLを発行して比較する。
CSVテーブル
最初にCSVテーブルに対して項目clientidだけを取得する以下のSQLを発行する。
select clientid from temp_humi_table
Run time | 2.1 seconds |
Data scanned | 8.25 MB 実質CSVテーブルを全てスキャンしている |
Parquetテーブル
次にParquetテーブルに対して項目clientidだけを取得する以下のSQLを発行する。
select clientid from temp_humi_pq_table
Run time | 1.94 seconds |
Data scanned | 0.13 KB |
比較結果
Run timeはそれほど大きな差は出なかった。
しかしデータのスキャン量は8.25 MBに対して0.13 KB(0.00013MB)なので1/63,461になっている。
ファイルサイズの1/40に対してスキャン量は大きく減少している事が分かるのだが、注意したいのは取得する項目によってスキャン量は大きく異なるという事。
試しにhumidity(浮動小数点)をselectした所、5.88KB(1/1,403)という結果だった。
また項目の値もスキャン量に影響を与えているという事が予測できる。
当初取得したclientidという項目はデータをコピーして作成した事もあり、ほとんどの列で同一の値が入っている。
Parquetはデータを圧縮しているので同一の値が入っている列は圧縮されて結果的にスキャン量が少なくなったのかも知れない。
本番条件に近いデータやwhere句で条件指定した場合等、他のパターンもいずれ試してみたい。
この記事が何処かで誰かの役に立つことを願っている。
尚、当記事中の商品へのリンクはAmazonアソシエイトへのリンクが含まれています。Amazonのアソシエイトとして、当メディアは適格販売により収入を得ていますのでご了承ください。
最近のコメント