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.StringText |
|
int |
intIntWritable |
|
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メソッドがあっても関係ない。 |