Apache PigでZipファイルをロード
経緯
仕事でHadoopを使うとき、gzip/bzipは標準で読み込めるがzipは読み込めなかった。困る。
Hadoopの本流でzipファイルを読む機能がマージされてないまま放置されていることに気づく
1. It does not split the zip files efficiently. This is because there is no way in Java to construct a zip input stream that permits random seeks given a zip entry name.
2. Java's handling of large zip file is not robust.
と、言われてます。1はよくわかりませんが、2については How to iterate zip file records (java.util.zip.ZipFile, java.util.zip.ZipInputStream) - Java Performance Tuning Guide に書かれているように、Java7からは2GB超えファイルにも標準で対応しています。
Map/Reduce
さっきのチケットの中で、Map/Reduceを拡張して読めるようにしてるブログを見つけました。
あと、同じことやってる人を見つけた
つまりはApache PigのLoad関数はHadoopのInputFormatクラスを使用している。それはそれぞれのレコードに対してRecordReaderをとり、そしてTuple(かそれ以外の何か)に変換している。なので、zip圧縮されたファイルを読みたいのならば、どうしても自前のInputFormat/RecordReaderを書く必要がある。上記のサイトはすでにそれを用意してくれている。
使い方
- mvn packageなどを実行してjarファイルを作ってpigスクリプトに追加
%declare ZIPLOADER 'com.cotdp.pigudf.ZipLoader'; REGISTER target/com-cotdp-hadoop-1.0-SNAPSHOT.jar -- 全ファイル取得 A = LOAD 'src/test/resources/zip-01.zip' USING $ZIPLOADER(''); DUMP A; -- 改行を区切りにしてbagとして取得 A = LOAD 'src/test/resources/zip-01.zip' USING $ZIPLOADER('\r\n') AS (raw:bytearray); B = FOREACH A GENERATE FLATTEN($0) AS (raw:chararray); DUMP B;
今はほんとに中身を出力するだけ