Hive 0.10でROLLUP, CUBE, GROUPING SETSが入ったよ

最近Hiveをいじることはめっきりなくなりましたが1/11にHive 0.10がリリースされましたね。前の0.9が2012/4/30リリースだったことを考えると約8ヶ月ぶりのリリースですね。ちなみに僕がHiveを一番触っていた頃のバージョンは0.6だったりします。てへ。それに比べるとだいぶ機能追加されていますが今回はROLLUP, CUBE, GROUPING SETSについて書いてみたいと思います。

JIRAはこちら
[HIVE-3433] Implement CUBE and ROLLUP operators in Hive - ASF JIRA

いろんな軸で集計したい場合に商用DBならROLLUP, CUBE, GROUPING SETSといった機能が使えます。これらの機能がなんとHiveでも使えるようになりました。スバラシ。

Pigのほうが早く実装されるかと思いきやHiveのほうが早かったですね。この辺は以下に少し書きました。

SQL, PigのCUBE - wyukawa’s blog

上記ブログでも使ったサンプルデータでHiveのROLLUP, CUBE, GROUPING SETSを見ていきたいと思います。

DDLはこんな感じ

create table a(
  x string,
  y string,
  z int
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','

サンプルデータはこんな感じ

$ cat cube.csv 
dog,miami,12
cat,miami,18
turtle,tampa,4
dog,tampa,14
cat,naples,9
dog,naples,5
turtle,naples,1

で、こんな感じでロードします。

LOAD DATA INPATH '.../cube.csv' OVERWRITE INTO TABLE a

じゃあ最初にROLLUPいきます。こんな感じのHiveクエリーを実行します。

select x,sum(z) from a group by x with rollup

実行結果はこんな感じ。第一列、x列で集計した結果に加えて総計もNULL,63(=27+31+5)と表示されていますね。

NULL 63
cat 27
dog 31
turtle 5

ちなみにROLLUPはHive 0.9以下でも以下のようなクエリを実行することでUNIONを使わずに同等のことを実現できます。注意点はxがnullにならないこと。

SELECT xn, SUM(z) FROM a LATERAL VIEW explode(array(x,null)) e as xn group by xn

元ネタ
個別集計と全体集計を1回のHiveクエリで実行する - たごもりすメモ

いきなりこのクエリー見てもなんのこっちゃという感じですが以下のようなクエリーを実行するとイメージがわくと思います。集計用に1列足すわけですね。これがxn列です。これを作るためにarrayで配列作ってexplodeで展開します。全体集計用にキーがnullのものを作り出して全体集計を出す感じです。なのでもとの集計キーxにnullがあるとその値が全体集計のほうに集計されてしまってマズいわけですね。

select * FROM a LATERAL VIEW explode(array(x,null)) e as xn

実行結果

dog miami 12 dog
dog miami 12 NULL
cat miami 18 cat
cat miami 18 NULL
turtle tampa 4 turtle
turtle tampa 4 NULL
dog tampa 14 dog
dog tampa 14 NULL
cat naples 9 cat
cat naples 9 NULL
dog naples 5 dog
dog naples 5 NULL
turtle naples 1 turtle


次にCUBE行ってみましょう。

クエリはこんな感じ

select x,y,count(*),sum(z) from a group by x,y with cube

実行結果はこんな感じ。最初の行は全集計結果で、次の3行はy列での集計結果で、次のcatの3行は最初の行が次の2行の集計行でそれ以降のdog, turtleも同じ感じです。

NULL NULL 7 63
NULL miami 2 30
NULL naples 3 15
NULL tampa 2 18
cat NULL 2 27
cat miami 1 18
cat naples 1 9
dog NULL 3 31
dog miami 1 12
dog naples 1 5
dog tampa 1 14
turtle NULL 2 5
turtle naples 1 1
turtle tampa 1 4


GROUPING SETSの場合のクエリはこんな感じ

select x,y,count(*),sum(z) from a group by x,y grouping sets(x,y)

実行結果はこんな感じ。最初の3行がy列での集計結果で後半の3行がx列での集計結果ですね。

NULL miami 2 30
NULL naples 3 15
NULL tampa 2 18
cat NULL 2 27
dog NULL 3 31
turtle NULL 2 5


CUBE, GROUPING SETSに関してもHive 0.9以下でUNIONを使わずに実現できるかはちょっとわかりません。

いじょ。