Alibaba CloudのE-MapReduceを利用し、SELECT文の実行は、テーブルに含まれる全データをスキャンします。WHERE句を指定し、特定の条件に合致するデータを抽出する場合、大量のデータを読み込んだにも関わらず、ごく一部のデータしか利用しないケースが想定されます。例えば、時系列にならんだログデータを集計する場合、特定の日にちのデータのみを集計したい時に、すべてのデータの日にちのデータをスキャンするのは明らかに無駄だと言えます。
そこで、特定の条件で分割して、パーティションとの単位でデータを保存しておく方法が推薦されます。今回の記事は、E-MapReduceでHiveの動的パーティションの利用方法について、皆さんにご紹介させて頂きたいと考えております。
- 前提
- EMR-3.16.0
- クラスタータイプは Hadoop
- ハードウェア構成(Header)はecs.sn1ne.2xlargeを1台
- ハードウェア構成(Worker)はecs.sn1ne.2xlargeを3台
# cat /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)
# uname -r
3.10.0-693.2.2.el7.x86_64
# hive --version
Hive 2.3.3
Git git://build.emr.com/root/sl/hive/newhb/emr-hive -r e2f827081ca7c8faa3d28b8fd2e7ab74919a1744
Compiled by root on Sat Sep 8 09:43:53 CST 2018
From source with checksum 6c51a2a446502e34b0de1038c17616cd
# hadoop version
Hadoop 2.7.2
Subversion http://gitlab.alibaba-inc.com/soe/emr-hadoop.git -r d2cd70f951304b8ca3d12991262e7e0d321abefc
Compiled by root on 2018-11-30T09:31Z
Compiled with protoc 2.5.0
From source with checksum 4447ed9f24dcd981df7daaadd5bafc0
This command was run using /opt/apps/ecm/service/hadoop/2.7.2-1.3.2/package/hadoop-2.7.2-1.3.2/share/hadoop/common/hadoop-common-2.7.2.jar
- Hiveの動的パーティション
# ossutil ls oss://dyn-part-test/
LastModifiedTime Size(B) StorageClass ETAG ObjectName
2019-02-21 15:06:44 +0800 CST 0 Standard D41D8CD98F00B204E9800998ECF8427E oss://dyn-part-test/input/
2019-02-21 15:07:39 +0800 CST 113 Standard 4E4E83C9B653C3D39715049D8F7231EA oss://dyn-part-test/input/foo.txt
10,20120101,100,10
10,20120101,101,20
11,20120102,100,30
11,20120102,101,40
12,20120103,100,50
12,20120103,101,60
CREATE EXTERNAL TABLE input_tab (
pid INT,
dt INT,
sid INT,
sm INT
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
LOCATION 'oss://dyn-part-test/input/';
CREATE EXTERNAL TABLE output_tab (
pid INT,
sm INT
)
PARTITIONED BY(
sid INT,
dt INT
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
STORED AS ORC
LOCATION 'oss://dyn-part-test/output/';
ここからポイントですが、データ挿入(OVERWRITEの代わりにINTOを指定することが可能です。)の際に、パーティションキーの値を明記すれば、静的な振り分けになりますが、値を記述しなければ、動的に振り分けられます。
SET hive.exec.dynamic.partition = true;
SET hive.exec.dynamic.partition.mode = nonstrict;
INSERT OVERWRITE TABLE output_tab PARTITION (sid, dt)
SELECT pid, sm, sid, dt
FROM input_tab;
再度バケットとディレクトリを確認すると、テーブルデータがパーティションごとに格納されるのが分かりました。
# ossutil ls oss://dyn-part-test/output/
LastModifiedTime Size(B) StorageClass ETAG ObjectName
2019-02-22 16:22:04 +0800 CST 0 Standard D41D8CD98F00B204E9800998ECF8427E oss://dyn-part-test/output/
2019-02-22 16:22:02 +0800 CST 0 Standard D41D8CD98F00B204E9800998ECF8427E oss://dyn-part-test/output/sid=100/
2019-02-22 16:22:03 +0800 CST 0 Standard D41D8CD98F00B204E9800998ECF8427E oss://dyn-part-test/output/sid=100/dt=20120101/
2019-02-22 16:22:03 +0800 CST 232 Standard 114F0402770283A9CAB84A8F0F4C864C oss://dyn-part-test/output/sid=100/dt=20120101/000000_0
2019-02-22 16:22:03 +0800 CST 0 Standard D41D8CD98F00B204E9800998ECF8427E oss://dyn-part-test/output/sid=100/dt=20120102/
2019-02-22 16:22:03 +0800 CST 245 Standard 444A0B2323EDB861D5142F6E7C5FE222 oss://dyn-part-test/output/sid=100/dt=20120102/000000_0
2019-02-22 16:22:02 +0800 CST 0 Standard D41D8CD98F00B204E9800998ECF8427E oss://dyn-part-test/output/sid=100/dt=20120103/
2019-02-22 16:22:03 +0800 CST 245 Standard C036552D01C4835AEA681657C5BF808F oss://dyn-part-test/output/sid=100/dt=20120103/000000_0
2019-02-22 16:22:02 +0800 CST 0 Standard D41D8CD98F00B204E9800998ECF8427E oss://dyn-part-test/output/sid=101/
2019-02-22 16:22:03 +0800 CST 0 Standard D41D8CD98F00B204E9800998ECF8427E oss://dyn-part-test/output/sid=101/dt=20120101/
2019-02-22 16:22:03 +0800 CST 245 Standard 7421C8FC9DB4BA94646F77CAADE17E56 oss://dyn-part-test/output/sid=101/dt=20120101/000000_0
2019-02-22 16:22:03 +0800 CST 0 Standard D41D8CD98F00B204E9800998ECF8427E oss://dyn-part-test/output/sid=101/dt=20120102/
2019-02-22 16:22:03 +0800 CST 245 Standard FCA3F020AF70EB6B9AA64616EACA639A oss://dyn-part-test/output/sid=101/dt=20120102/000000_0
2019-02-22 16:22:03 +0800 CST 0 Standard D41D8CD98F00B204E9800998ECF8427E oss://dyn-part-test/output/sid=101/dt=20120103/
2019-02-22 16:22:03 +0800 CST 245 Standard FDEE77829735C291DCC96233571F0E7C oss://dyn-part-test/output/sid=101/dt=20120103/000000_0
ローカルにダウンロードして、中身を確認すると ORC という文字列が見えるため、確かにORCファイルです。
# ossutil cp oss://dyn-part-test/output/sid=101/dt=20120103/000000_0 .
Succeed: Total num: 1, size: 245. OK num: 1(download 1 objects).
0.071985(s) elapsed
# cat output/sid\=101/dt\=20120103/000000_0
ORC
P+
P+
xxxPNNxH?b?``???ь`? L3?l`?I?M?????@<?R?b?`
`???`b??????**$*??`(???`???QP?`T???bbd?b.?L?b*?Ub?`aF+?+F!6 8?B?B?"??aK??"
(!0??ORC
- パーティションの追加
ALTER TABLE output_tab ADD PARTITION (sid='102', dt='20120101') location 'oss://dyn-part-test/output/sid=102/dt=20120101/' PARTITION (sid='103', dt='20120102') location 'oss://dyn-part-test/output/sid=103/dt=20120102/';
パーティションを確認したら、追加したパーティションを見えます。
hive> show partitions output_tab;
OK
sid=100/dt=20120101
sid=100/dt=20120102
sid=100/dt=20120103
sid=101/dt=20120101
sid=101/dt=20120102
sid=101/dt=20120103
sid=102/dt=20120101
sid=103/dt=20120102
- パーティションの削除
ALTER TABLE output_tab DROP IF EXISTS PARTITION (sid='103',dt='20120102');
hive> show partitions output_tab;
OK
sid=100/dt=20120101
sid=100/dt=20120102
sid=100/dt=20120103
sid=101/dt=20120101
sid=101/dt=20120102
sid=101/dt=20120103
sid=102/dt=20120101
- 最後