2.入出力
MapReduceは、外から見ると以下のことをするフレームワークです。
- ファイルを入力しオブジェクトでできた<Key, Value>ペアに変換する
- 結果の<Key, Value>ペアを生成する、MapとReduce処理を実行する
- 別のファイルに出力する
このため、「ファイルから入力する」「データをオブジェクト化する」「ファイルに出力する」というクラス群を持っており、MapReduceジョブのJavaプログラムでもこれらにアクセスすることになります。これを理解しておかないと、MapReduceプログラムは理解できそうにありません。
MapReduceの入力と出力のインターフェースは、MapReduceの重要な特徴を持っています。それは、以下の組み合わせでデータのやりとりをすることです。
<Key, Value>
Hadoop MapReduceの入力と出力は、あらかじめ提供されている「InputFormat」「OutputFormat」インターフェースによって行われます。これらを「入力フォーマット」「出力フォーマット」と呼び、いろいろな種類があります。キー(Key)とバリュー(Value)は、置き換えが可能です。
入力フォーマットが入力できるファイルは、複数にわかれていても構いません。ファイル単体やパス(フォルダ)を指定し、InputFormatのクラスメソッド、addInputPath()や、addInputPaths()メソッドでパスを追加することで多くのファイルを入力にできます。
入力フォーマットや出力フォーマットはデフォルトで以下の2つがセットされています。
- 入力フォーマット:TextInputFormat
- 出力フォーマット:TextOutputFormat
テキストファイルを入力にします。レコードは、改行で区切られた「行」、キーはlong値で、先頭からのバイト数、バリューは1行のテキストです。
テキストファイルに出力します。デフォルトでは、キーとバリューはタブで区切られます。キーとバリューの型は、外からセットします。
ここで分かるのは、入力をデフォルトのまま使うなら、自動的に入力は次のようになる、ということです。
| 型 | オブジェクトクラス | 内容 | |
| キー | long | LongWritable | 入力の先頭からのバイト位置 |
| バリュー | String | Text | 1行 |
InputFormat、OutputFormatには、他にも以下のようにさまざまな種類があり、必要に応じて使い分けます。
- InputFormat
- OutputFormat
CombineFileInputFormat、KeyValueTextInputFormat、StreamInputFormat、NLineInputFormat、SequenceFileInputFormat、SequenceFileAsBinaryInputFormat、SequenceFileAsTextInputFormat、SequenceFileInputFilter、CompositeInputFormat、DBInputFormat、EmptyInputFormat
SequenceFileOutputFormat、SequenceFileAsBinaryOutputFormat、MapFileOutputFormat、MultipleOutputFormat、MultipleTextOutputFormat、MultipleSequenceFileOutputFormat、NullOutputFormat、DBOutputFormat、FilterOutputFormat、LazyOutputFormat
シリアライザ
さて、ここで見慣れない名称「LongWritable」「Text」が出てきました。これはなんでしょう?
Hadoopは、ファイルからオブジェクトへ入力、オブジェクトからファイルへ出力、とするとき、Javaのスタンダードなオブジェクトを使わずに専用のオブジェクトを使います。例えば、テキストファイルに文字で書いてある数字をlong型で読み取ったり、Int型のデータを文字列に書き出したりする、ということです。Javaのスタンダードなオブジェクトやプリミティブ型を使わない理由はいろいろありますが、もっとも有力な理由は「MapReduceが、KeyとValueの組み合わせを自由に選択できる」ようにするためです。JavaのLong型、Int型、などを共通に扱おうとすると、Object型を引数としてメソッドなどを定義しなければならず、あまりに汎用すぎるものになってしまいますし、Serializableを使うと、入出力ファイルがバイナリー型式の複雑なものになってしまい、扱いにくいからです。
Hadoopでは、こういったファイルとの入出力(シリアライズ、デシリアライズ)に使うオブジェクト群を「Writable」と言います。Writableは、MapタスクやReduceタスクの出力メソッド「write」に書き出せる(writable)オブジェクトという意味と思われます。例えば、プリミティブ(数値など)型に対して、表X.のような型を使ってフレームワークの中でデータの受け渡しが行われます。
| 型 | Hadoopのラッパー |
| boolean | BooleanWritable |
| byte | ByteWritable |
| int | IntWritable VIntWritable |
| float | FloatWritable |
| long | LongWritable VLongWritable |
| double | DoubleWritable |
文字列は、TextというWritableを使います。このほかに、NullWritable、BytesWritable、MD5Hash、ObjectWritable、GenericWritableといったものがあります。これらは、Writableインターフェースを実装したクラスです。ここまで読んだ時点で、もう一度最初から読み直していただくとより理解が深まると思います。
