たごもりすメモ

コードとかその他の話とか。

Hive GenericUDFの挙動がおかしい場合

コンストラクタで初期化処理をやってしまっていないか気をつけよう。

通常 GenericUDF を継承したUDFを実装する場合、初期化処理は initialize メソッド内で行う。コンストラクタで行ってはいけない。それでも古いほうのHiveのバージョンでは動くケースがあったようだが、Hive 0.13で動かなくなっているケースが出て難儀した。
なにしろデータソースによって動いたり動かなかったりする。普通にカラムの入力データを食わせると動かないが、入力データをHiveQLの中で文字列リテラルで与えると動いたりして地獄だった。動かないというのもエラーになるとかじゃなくて、なんかありえない挙動を示す。正規表現マッチのグルーピングが本来の挙動に対してひとつズレた結果が返ってくるとか。

詳しくはそこまで調べてないのであまり書くと嘘になってしまうが、どうもUDFのインスタンスを生成するタイミングと、それを実際に各Task内でinitializeするタイミングが異なるせいではないか、そしてその間に何らかのシリアライズ・デシリアライズが挟まってるのではないか、という感じ。Serializableでない内部状態をコンストラクタ内で作ってしまうと、それが再現できずに(あるいは中途半端に再現されて)以降の処理がおかしいことになる。

ということで、GenericUDFを継承したUDFを作るとき、初期化処理は initialize() メソッド内でやりましょう。

なおUDFを継承したUDFを作るとき(ややこしいな!)は、そのコンストラクタは実際にはGenericUDFのinitialize()から呼ばれるので、使ってよい、ということでした。id:myui さんに教えてもらった。詳しい人がそのへんに座ってるの超便利……!