AWS Athenaで列試行のデータストレージ形式Parquetのデータを扱ってみた | そう備忘録

AWS Athenaで列試行のデータストレージ形式Parquetのデータを扱ってみた

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がインストールされた。

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
SQLの発行

Run time

2.1 seconds

Data scanned

8.25 MB

実質CSVテーブルを全てスキャンしている

Parquetテーブル

次にParquetテーブルに対して項目clientidだけを取得する以下のSQLを発行する。

select clientid from temp_humi_pq_table
ParquetテーブルへのSQLの発行

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のアソシエイトとして、当メディアは適格販売により収入を得ていますのでご了承ください。

souichirou

やった事を忘れない為の備忘録 同じような事をやりたい人の参考になればと思ってブログにしてます。 主にレゴ、AWS(Amazon Web Services)、WordPress、Deep Learning、RaspberryPiに関するブログを書いています。 仕事では工場に協働ロボットの導入や中小企業へのAI/IoT導入のアドバイザーをやっています。 2019年7月にJDLA(一般社団法人 日本デイープラーニング協会)Deep Learning for GENERALに合格しました。 質問は記事一番下にあるコメントかメニュー上部の問い合わせからお願いします。

おすすめ

質問やコメントや励ましの言葉などを残す

名前、メール、サイト欄は任意です。
またメールアドレスは公開されません。