なんとな~くしあわせ?の日記

「そしてそれゆえ、知識そのものが力である」 (Nam et ipsa scientia potestas est.) 〜 フランシス・ベーコン

Apache PigでZipファイルをロード

github.com

経緯

仕事で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を書く必要がある。上記のサイトはすでにそれを用意してくれている。

ひしだまさんのサイトでLoadFuncの拡張方法を知る

Javaと言えばひしだまさん。

ここでLoadFuncについて学んだらすぐにできた。

使い方

  • 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;

今はほんとに中身を出力するだけ

Hadoop関連ソフトウェアを手っ取り早くパッケージでインストールする

Apache Bigtop

Bigtop - Apache Bigtop

Bigtop is an Apache Foundation project for Infrastructure Engineers and Data Scientists looking for comprehensive packaging, testing, and configuration of the leading open source big data components. Bigtop supports a wide range of components/projects, including, but not limited to, Hadoop, HBase and Spark.

Bittopは包括的なパッケージ、テストそしてオープンソースビッグデータ構成要素の設定を探しているインフラエンジニアやデータサイエンティストのためのApacheソフトウェア財団のプロジェクトです。Bigtopは広い範囲の構成要素/プロジェクトを含んでおり、しかしながらその範囲はHadoop、HBaseやSparkに限りません。

Debianにインストール

# cd /etc/apt/sources.list.d
# wget http://www.apache.org/dist/bigtop/bigtop-1.1.0/repos/debian8/bigtop.list
# apt-get update
# apt-get install pig

Apache PigでShift_JISテキストをUTF-8化

Apache PigでShift_JISテキストをUTF-8

hdfs上にファイルを取り込む際、デフォルトの文字コードUTF-8らしい。
どうやって取り込むか悩んだが、UDFという方法を見つけた。

User Defined Function:UDF

ひしだまさんのサイトに載っている通りEvalFuncを継承するクラスを作成し、exec関数を実装する。

Conv2Utf8
  • このソースをmavenを使ってjarファイル化し、「conv2utf8-1.0-SNAPSHOT.jar」とかにしておく
package your.package.name;

import java.io.IOException;
import org.apache.pig.impl.util.WrappedIOException;

import org.apache.pig.EvalFunc;
import org.apache.pig.data.Tuple;
import org.apache.pig.data.TupleFactory;
import org.apache.pig.data.DataType;
import org.apache.pig.data.DataByteArray;

public class Conv2Utf8 extends EvalFunc<String> {

    public String exec(Tuple input) throws IOException {
	if (input == null || input.size() == 0) {
	    return null;
	}
	DataByteArray barray = (DataByteArray) input.get(0);
	byte[] bytes = barray.get();
	return new String(bytes, "MS932");
    }
}
test.pig

REGISTER conv2utf8-1.0-SNAPSHOT.jar

TEMP = LOAD 's3://xxxxx/sample.txt' AS (raw_data:bytearray);
DATA = FOREACH TEMP GENERATE your.package.name.Conv2Utf8(raw_data);

DUMP DATA;

Pigのデータ型

Pig Latin Basics

これを使えばzipファイル等も解凍できるなあと思った