Hiveのユーザー定義関数(User Defined Function:UDF)の作り方のメモ。
|
|
Hiveで使う関数を作るには、org.apache.hadoop.hive.ql.exec.UDFを継承したクラスを作成し、「evaluate」という名前のメソッドを用意する。
Hive上で自作関数を実行すると、このevaluateメソッドが呼ばれる。
(『Hadoop徹底入門』p.224には「evaluateメソッドを継承する」と書かれているが、親クラスにevaluateというメソッドが定義されているわけではないので、「継承」と言うと語弊がある気がする)
evaluateメソッドの引数や戻り型は自由。
Hive上で呼び出すときにそれらに応じた型の値を指定することになる。
package sample; import org.apache.hadoop.hive.ql.exec.UDF;
public class SampleUDF extends UDF { public String evaluate(String s) { return s + s; } }
必要となるjarファイルは以下の通り。
jarファイル | 備考 | Eclipseのソースの添付 |
---|---|---|
HIVE_HOME/lib/hive-exec-0.7.1.jar | UDFクラス | C:/cygwin/usr/local/hive-0.7.1/src |
HADOOP_HOME/hadoop-0.20.2-core.jar | HadoopのTextやIntWritable等を使う場合 | C:/cygwin/usr/local/hadoop-0.20.2/src |
Hiveにはjarファイルを読み込ませるので、作ったクラスをjarファイル化しておく。
<?xml version="1.0" encoding="Shift_JIS"?> <project name="hive0.7.1" default="jar" basedir="."> <property name="src" location="../src" /> <property name="classes" location="../classes" /> <target name="jar"> <jar jarfile="C:/cygwin/tmp/hiveudf.jar"> <fileset dir="${classes}" includes="**/*.class" /> <fileset dir="${src}" includes="**/*.java" /> </jar> </target> </project>
Hiveから自作のユーザー定義関数を使用するには、まずクラスの入ったjarファイルを読み込ませ、
CREATE TEMPORARY FUNCTIONによって関数名(とクラス名)を定義する。
hive> add jar C:/cygwin/tmp/hiveudf.jar; Added C:/cygwin/tmp/hiveudf.jar to class path Added resource: C:/cygwin/tmp/hiveudf.jar
※追加したjarファイルは「list jars;
」で一覧表示、「delete jar ファイル名;
」で除去できる。
hive> create temporary function myfunc as 'sample.SampleUDF'; OK
hive> select myfunc(項目) from テーブル;
※関数はDROP TEMPORARY FUNCTIONで削除できる。
自作のユーザー定義関数もSHOW FUNCTIONSやDESCRIBE FUNCTIONによって確認できる。
(SHOW FUNCTIONSには、正規表現で関数名のパターンを指定することが出来る。SHOW TABLESと同様)
hive> show functions 'm.*'; OK map max min minute month myfunc
hive> desc function myfunc; OK There is no documentation for function 'myfunc'
ドキュメントが無いと言われた^^;
ドキュメント(関数の説明)はユーザー定義関数クラスのアノテーションで記述する。
import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF;
@Description(name = "sample-name", value = "_FUNC_ sample-description", extended = "sample-extended") public class SampleUDF extends UDF { 〜 }
Descriptionアノテーションのvalueに概要、extendedに詳細(使用例など)を記述する。
valueやextended内に「_FUNC_」というキーワードを入れると、create functionで指定した関数名に置換される。
↓
hive> desc function myfunc; OK myfunc sample-description hive> desc function extended myfunc; OK myfunc sample-description sample-extended
ユーザー定義関数クラス内のevaluateメソッドはオーバーロードすることが出来る。(引数違いのメソッドを定義できる)
Hiveから使う際は引数に応じて正しいevaluateメソッドが呼ばれる。(引数の個数が不定な可変長引数も可)
Hiveのデータ型 | UDFで使える型 | 更新日 |
---|---|---|
string |
java.lang.String Text |
|
int |
int IntWritable |
|
double |
double
DoubleWritable |
|
boolean |
boolean
BooleanWritable |
|
array<型> |
java.util.List<型> |
|
map<キー型, 値型> |
java.util.Map<キー型, 値型> |
|
struct |
class |
2011-09-14 |
public class SampleUDF2 extends UDF { public Map<String, Integer> evaluate(String key, int value) { Map<String, Integer> map = new HashMap<String, Integer>(); map.put(key, value); return map; } public List<String> evaluate(String... values) { return Arrays.asList(values); } }
hive> create temporary function sample2 as 'sample.SampleUDF2'; hive> select sample2('key', 123), sample2('a', 'b', 'c') from テーブル;
booleanを返すevaluateメソッドを作れば、where句に直接指定することも出来る。
public class BooleanUDF extends UDF { public boolean evaluate(int n, int m) { return n == m; } }
hive> create temporary function sample3 as 'sample.BooleanUDF'; hive> select 't' from テーブル where sample3(123, 123);
evaluateの戻り値の型とHiveQLでの使い方の例。[2011-09-14]
UDF | HiveQL | 備考 | |
---|---|---|---|
配列 | public List<String> evaluate() { |
select a[0], a[1], a[2] from( |
Listを返すと、HiveQLでは配列になる。 |
マップ | public Map<String, String> evaluate() { |
select m['abc'], m['def'], m['ghi'] from( |
Mapを返すと、HiveQLでもマップになる。 |
構造体 | static class Sample { |
select s.abc, s.def, s.ghi from( |
クラスを返すと、HiveQLではStructになる。 クラスのフィールドが構造体の各要素の名称となる。 各フィールドがpublicである必要は無いし、 getterやsetterメソッドがあっても関係ない。 |