AWS SDK for PHP で学ぶ Athena
2017/08/08
株式会社サーバーワークス
カスタマーサポート課
すぎたに たかき
#2
⾃⼰紹介
l すぎたに たかき
l 2016/09 SWX JOIN
l カスタマーサポート課
l ⼤阪オフィス & おうち 勤務
l 技術
l AWSまだまだ勉強ちゅう!
l プログラミング⼤好き(たぶん)
l pythonも勉強ちう!
l プライベート
l 無類のイヌ好き
l 泳ぐ〜 (週2〜3回...2,000m/回)
2
うろちょろしてるコミュニティー
前回にも弊社柏尾がAthenaについてお話させていただきました
3
サーバーワークス
技術ブログ
こちらも
あわせてご覧下さい
4
Athenaとの出会い
動かなかったプログラム
Athenaから早くデータを取ってこれた!
PARTITION機能
その1
その2
AWS SDK for PHP v3 でAthenaにアクセス
■Contents
Athenaとの出会い
5
Amazon	Athena	はインタラクティブなクエリサービスで、Amazon	S3	内のデー
タを標準的な SQL	を使⽤して簡単に分析できます。
Athena	はサーバーレスなので、インフラストラクチャの管理は不要です。
実⾏したクエリに対してのみ料⾦が発⽣します。
6
S3 bucket
Athena
SDK for PHP
SQL
SQLでS3に保存したデータがとれる幸せ
7
S3 bucket Athena
保存できるデータフォーマット
Supported	Formats	and	SerDes
The	data	formats	presently	supported	are:
Avro
Apache	Web	Server	logs	(RegexSerDe)
CloudTrail
CSV	(OpenCSVSerDe)
Custom	Delimiters
Grok
JSON
ORC
Parquet	Serde
回ってきたLT当番
8
社内LTで発表したネタ
9
Firehose S3 bucket
Athena
QuickSight
温度
湿度
⽇時
050-XXXX-XXXX
ただいまの
温度は
29℃です
SDK PHP
EC2
※ここでEC2をつかってしまったので、ぼくの負けです...サーバーレスとか、かっこいいことしたかった...
Special Thanks
JAWS-UG 関⻄ IoT⽀部
Soracom-UG
Twilio-UG
json
Raspberry Pi
SDK Python
データに対してSQLをつかえるなら最新のデータ取得は簡単!
10
フィールド
温度(tmp)
湿度(hum)
⽇時(time)
Athenaのテーブル
(iot_lt_tbl)
select *
from iot_lt_tbl
order by time DESC
limit 1
あれ!?
ぷー
ぷー
ぷー
!! AthenaのSQL処理時間かかりすぎ...
12
SQL
タイムアウト 15秒ぐらい
SQLをAthenaに投げて
お返事があるまで20秒ぐらい
※対象データ件数:約12,000件
んんん!?
13
PARTITION機能
そこで登場する⼤切な機能
データを分割することで、各クエ
リでスキャンされるデータの量を
制限することができ、パフォーマ
ンスが向上し、コストが削減され
ます。
2つのPARTITION設定⽅法
1. S3フォルダー内でデーターがhiveフォーマットで
PARTITION化されている場合
2. 分割されていない場合
パターン1の例
S3フォルダー内でデーターがhive
フォーマットでPARTITION化
されている場合
パーティションデータを⾃動的にMSCK	REPAIR	TABLEで追加できる
17
こんな感じが hiveフォーマット
$	aws	s3	ls	s3://sabawa-no-wa-2/ondo_data/	
PRE	ym=1968-08/	
PRE	ym=1968-09/
PRE	ym=1968-10/
PRE	ym=1968-11/	
PRE	ym=1968-12/	
PRE	ym=1969-01/		
PRE	ym=1969-02/		
PRE	ym=1969-03/	
PRE	ym=1969-04/	
PRE	ym=1969-05/
18
s3://sabawa-no-wa-2/
ondo_data
ym=1999-11
PARTITION(パターン1)
ym=1999-12
ym=2000-01
ym=2000-02
ym=2000-03
ym=2000-04
1999年11⽉のデータcsvのみ保存する
1999年12⽉のデータcsvのみ保存する
2004年04⽉のデータcsvのみ保存する
フォルダー名が hoge=xxxxx	の形式
ここだけさがして〜
S3のマネージメントコンソールはこんな感じ
19
例1)データ形式(⽇付と温度と湿度が⼊ってる)
フィールド 型
⽇時(hiduke) string
温度(tmp) float
湿度(hum) float
20
1968-08-22,29.9,20.1
S3に⼊ってる1つのデータ例
Athenaのテーブル形式
データベース名:sabawa_no_wa_2_db
テーブル名 :on_shitudo_tbl
ex)	
1968-08-xx	からの⼤阪市におけ
る1時間おきの最⾼気温と平均湿
度を保存した。
パーテーションをつくると!
フィールド 型
⽇時(hiduke) string
温度(tmp) float
湿度(hum) float
ym string
21
Athenaのテーブル形式
データベース名:sabawa_no_wa_2_db
テーブル名 :on_shitudo_tbl
Athenaのマネジメントコンソールから Add table
22
データベース名
テーブル名
S3バケット+フォルダー
Data Formatを選択する
23
Columnsの設定
24
Column名
データ型
Column名
データ型
Column名
データ型
PARTITIONの設定
25
フォルダー名の右辺の名前
ym=2015-02
フォルダー名の右辺をどのような
型として認識するか
できあがったCREATE⽂
26
CREATE EXTERNAL	TABLE IF	NOT	EXISTS	sabawa_no_wa_2_db.on_shitudo_tbl (
`hiduke` string,
`tmp` float,
`hum`	float
)	
PARTITIONED	BY (
ym string
)
ROW	FORMAT	SERDE	'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
WITH	SERDEPROPERTIES	(	'serialization.format'	=	',',	'field.delim'	=	','	)	
LOCATION 's3://sabawa-no-wa-2/ondo_data/'
TBLPROPERTIES ('has_encrypted_data'='false');
MSCK REPAIR TABLE
27
MSCK	REPAIR	TABLE	[テーブル名]
実際のパーテーションを作る感じ・・(?)
作成されたPARTITIONの確認
28
SHOW	PARTITIONS	[テーブル名]
作成されたPARTITION
これがSQLのWHERE句に記述できる
わざとPARTITIONを使わないQuery
29
Run	time:	22.52	seconds,Data	scanned:	357.52KB
PARTITIONを使った場合
30
Run	time:	3.68	seconds,Data	scanned:	0.64KB
ちょっとおまけ
データーを圧縮するといいらしい
CREATE	EXTERNAL	TABLE	IF	NOT	EXISTS	sabawa_no_wa_2_db.on_shitudo_zip_tbl	(
`hiduke`	string,
`tmp`	float,
`hum`	float
)	PARTITIONED	BY	(
ym	string
)
ROW	FORMAT	SERDE	'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
WITH	SERDEPROPERTIES	(
'serialization.format'	=	',',	'field.delim'	=	','	)	
LOCATION	's3://sabawa-no-wa-2/ondo_data/'	
TBLPROPERTIES ("orc.compress"="	ZLIB");
※ Athenaの圧縮で使うとき snappy というのがよいらしい
tblproperties	("parquet.compress"="SNAPPY");
(でも、あまり変わらなかった〜)
詳しくは〜
33
https://aws.amazon.com/jp/blogs/big-data/top-10-
performance-tuning-tips-for-amazon-athena/
http://google.github.io/snappy/
パターン2の例
データーが分割されてない場合
35
こんな感じ・・
$	aws	s3	ls		s3://wankoro-firehose/			--recursive	
2017-06-20 20:56:05 114 2017/06/20/11/wankoro-firehose-1-2017-06-20-11-55-01-87e581d0-f397-4497-bdf5-ea94ff6a22f3
2017-06-20 20:58:06 57 2017/06/20/11/wankoro-firehose-1-2017-06-20-11-57-03-ad97cc3a-7f2f-4c62-bb47-7dadf273e10c
2017-06-20 20:59:09 114 2017/06/20/11/wankoro-firehose-1-2017-06-20-11-58-04-ea1bf0c0-1f0d-4c8b-9762-9e26b0acf8a5
2017-06-20 21:01:10 57 2017/06/20/12/wankoro-firehose-1-2017-06-20-12-00-06-77d43b79-9b0a-4b69-9438-347055f7ca60
2017-06-20 21:02:10 57 2017/06/20/12/wankoro-firehose-1-2017-06-20-12-01-08-84f78543-c7e9-497b-bc5f-c62f5831ef12
2017-06-20 21:03:13 114 2017/06/20/12/wankoro-firehose-1-2017-06-20-12-02-09-4da76871-4522-412d-9585-3e220b5a6e7f
2017-06-20 21:05:15 57 2017/06/20/12/wankoro-firehose-1-2017-06-20-12-04-11-9a99e5c2-2a36-4541-aa37-6c9fd7c31c8c
36
s3://wankoro-backet/
2017 06 28
29
30
07 01
02
03
PARTITION機能!!
ここだけさがして〜
2017年06⽉28⽇のデータのみ保存する
2017年06⽉29⽇のデータのみ保存する
2017年07⽉03⽇のデータのみ保存する
例2)データ形式(⽇付と温度と湿度が⼊ってる)
フィールド 型
温度(tmp) float
湿度(hum) float
⽇時(time) timestamp
37
{"tmp": 28.9, "hum": 65.5, "time": "2017-07-06 17:07:02"}
S3に⼊ってる1つのデータ例 (json形式)
Athenaのテーブル形式
データベース名:iot_lt_db
テーブル名 :iot_lt_tbl
38
s3://wankoro-backet/ Athenaのテーブルをつくる時、こんな感じで
CREATE TABLEします。
ex)
CREATE EXTERNAL	TABLE iot_lt_db.iot_lt_tbl
(	
tmp float,	
hum float,	
time string	
)	
PARTITIONED	BY (year string	,	month string,	day string)	
ROW	FORMAT	serde	'org.apache.hive.hcatalog.data.JsonSerDe'	
LOCATION 's3://wankoro-backet/'	;
PARTITION機能!!
フィールド 型
温度(tmp) float
湿度(hum) float
⽇時(time) timestamp
Athenaのテーブル形式
iot_lt_db.iot_lt_tbl
パーテーション 型
年(year) string
⽉(hum) string
⽇(time) string
フィールド定義
PARTITION定義
データフォーマット定義
S3データ位置定義
39
ALTER TABLE iot_lt_db.iot_lt_tbl
ADD PARTITION (year=ʼ2017',month=ʼ07',day=ʼ02')
location 's3://wankoro-backet/2017/07/02/'
フィールド
温度(tmp)
湿度(hum)
⽇時(time)
Athenaのテーブル
(iot_lt_tbl)
PARTITIONを追加しておくと、iot_lt_tbl に対して
このようなSQLを実⾏することができます。
select *
from iot_lt_db.iot_lt_tbl
where year = ʻ2017ʼ
and month = ʻ07ʼ
and day = ʻ02ʼ
order by time DESC
limit 1
本来、SQLのwhere句にはテーブ
ルにあるフィールドに対して条件を
書くことが基本ですが、追加した
パーテーションをwhereに書くこと
ができ、特定のS3フォルダを対象
に処理してくれます。
1つ1つ、パーテーションを作る必要がある・・・
40
s3://wankoro-backet/
2017 06 28
29
30
07 01
02
03
ex) 2017年07⽉02⽇だけ検索したい場合
あらかじめ、以下の様なSQLを実⾏し、
パーテーションを追加しておきます。
ALTER TABLE iot_lt_db.iot_lt_tbl
ADD PARTITION (year=ʼ2017',month=ʼ07',day=ʼ03')
location 's3://wankoro-backet/2017/07/03/'
パーテーションを作っていかないといけない・・・
ここだけさがして〜
PARTITION機能!!
41
select * from iot_lt_db.iot_lt_tbl
where time
BETWEEN date '2017-07-02' AND date '2017-07-03ʼ
order by time desc
limit 1
select * from iot_lt_db.iot_lt_tbl
order by time desc
limit 1
約20秒
約17秒
ちなみにこんな検索条件をつけても、RDSではないので速くなりません〜
※対象データ件数:約12,000件
42
SQL
タイムアウト 15秒ぐらい
PARTITION機能!!
SQLをAthenaに投げて
お返事があるまで5秒ぐらい
※対象データ件数:約12,000件
SQLをAthenaに投げて
お返事があるまで20秒ぐらい
PARTITION機能なし
PARTITION機能あり
AWS SDK for PHPで
Athenaを
使ってみる
44
全体的な流れ...
①IAMユーザを作り AthenaにアクセスできるRoleを付与する
・クレデンシャル情報(AWS	Access	Key	ID と AWS	Access	Key	ID)を保存しておく
②実⾏マシン(サーバー)にAWSコマンドをインストールする
③インストールしたaws	configure	を実⾏し、作ったIAMユーザのクレデンシャル情報を登録しておく
④実⾏マシン(サーバー)に AWS	SDK	for	PHP	v3	のインストール
⑤PHPにてコードを書く
IAMユーザを作り AthenaにアクセスできるRoleを付与する
45
AWS コマンドをインストールする
46
https://aws.amazon.com/jp/cli/
aws configure を実⾏ (作ったIAMユーザのクレデンシャル情報を登録)
47
[sabawano-wa@ip-10-0-0-142	~]$	cd		~
[sabawano-wa@ip-10-0-0-142	~]$	aws				configure				--profile=sabawa-no-wa
AWS	Access	Key	ID	[None]:	AKIAHOGEHOGEHOGEHOGEH
AWS	Secret	Access	Key	[None]: hoge123HOGE456/hoge123HOGE456/123HOGE456/
Default	region	name	[None]:	us-east-1
Default	output	format	[None]:	json
AWS SDK for PHP v3 のインストール
48
Requirements	:	PHP	>=	5.5.0
[sabawano-wa@ip-10-0-0-142	~]$	cd			~/athena_test
[sabawano-wa@ip-10-0-0-142	~]$	curl			-sS		 https://getcomposer.org/installer |			php
[sabawano-wa@ip-10-0-0-142	~]$	php					composer.phar					require	aws/aws-sdk-php
プログラムコードの概要
49
① AWS	SDK	for	PHP	のロード
② Athena	クライアント・インスタンスの作成
③ SQLの作成
④ SQLの実⾏
⑤ SQL実⾏中のステータスをwhileループしながら確認
⑥ SQLが完了するステータスが取得できたら、SQL結果の取得
⑦ 結果表⽰
サンプルコードは GitHubGist に貼っておきました
50
https://gist.github.com/wankormaru/d031824a2eb2c0232316b4cb5b8cb1b8
制限値をご確認ください
51
http://docs.aws.amazon.com/athena/latest/ug/service-limits.html
52
まとめ...
Athena のPARTITION機能を使うとよいかも
S3のデータがhive形式でPARTITION化されている場合
S3のデータが分割されていない場合
データは圧縮することができそうです
AWS SDK for PHP でサンプルを動かしました
制限値(Service Limit)に注意しましょう
ありがとうございました!
@wankoromaru_kun

さばわのわ#2 AWS SDK for PHP で学ぶAthena