1. 程式人生 > >hadoop SequenceFile 簡介/優缺點

hadoop SequenceFile 簡介/優缺點

1. 什麼是SequenceFile

1.1.sequenceFile檔案是Hadoop用來儲存二進位制形式的[Key,Value]對而設計的一種平面檔案(Flat File)。
1.2.可以把SequenceFile當做是一個容器,把所有的檔案打包到SequenceFile類中可以高效的對小檔案進行儲存和處理。
1.3.SequenceFile檔案並不按照其儲存的Key進行排序儲存,SequenceFile的內部類Writer提供了append功能。
1.4.SequenceFile中的Key和Value可以是任意型別Writable或者是自定義Writable。
1.5.在儲存結構上,SequenceFile主要由一個Header後跟多條Record組成,Header主要包含了Key classname,value classname,儲存壓縮演算法,使用者自定義元資料等資訊,此外,還包含了一些同步標識,用於快速定位到記錄的邊界。每條Record以鍵值對的方式進行儲存,用來表示它的字元陣列可以一次解析成:記錄的長度、Key的長度、Key值和value值,並且Value值的結構取決於該記錄是否被壓縮。

2.SequenceFile支援資料壓縮

2.1.SequenceFIle的內部格式取決於是否啟用壓縮,如果是壓縮,則又可以分為記錄壓縮和塊壓縮。
2.2.有一下三種類型的壓縮:
A.無壓縮型別:如果沒有啟用壓縮(預設設定)那麼每個記錄就由它的記錄長度(位元組數)、鍵的長度,鍵和值組成。長度欄位為4位元組。
B.記錄壓縮型別:記錄壓縮格式與無壓縮格式基本相同,不同的是值位元組是用定義在頭部的編碼器來壓縮。注意:鍵是不壓縮的。下圖為記錄壓縮:

在這裡插入圖片描述
C.塊壓縮型別:塊壓縮一次壓縮多個記錄,因此它比記錄壓縮更緊湊,而且一般優先選擇。當記錄的位元組數達到最小大小,才會新增到塊。該最小值由io.seqfile.compress.blocksize中的屬性定義。預設值是1000000位元組。格式為記錄數、鍵長度、鍵、值長度、值。下圖為塊壓縮:

在這裡插入圖片描述
3.優缺點

SequenceFile優點:
A.支援基於記錄(Record)或塊(Block)的資料壓縮。
B.支援splitable,能夠作為MapReduce的輸入分片。
C.修改簡單:主要負責修改相應的業務邏輯,而不用考慮具體的儲存格式。

SequenceFile的缺點
A.需要一個合併檔案的過程,且合併後的檔案不方便檢視。

4.具體程式碼實現

以下程式碼實現了讀寫SequenceFile的需求。

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.*;
import org.apache.hadoop.util.ReflectionUtils;

import java.io.IOException;


public class SequenceTest {

    public static final String output_path = "xxx";
    private static final String[] DATA = { "a", "b", "c", "d"};

    @SuppressWarnings("deprecation")
    public static void write(String pathStr) throws IOException {
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(conf);
        Path path = new Path(pathStr);

        SequenceFile.Writer writer = SequenceFile.createWriter(fs, conf, path, Text.class, IntWritable.class);
        Text key = new Text();

        IntWritable value = new IntWritable();
        for(int i = 0; i < DATA.length; i++) {
            key.set(DATA[i]);
            value.set(i);
            System.out.printf("[%s]\t%s\t%s\n", writer.getLength(), key, value);
            writer.append(key, value);
        }
        IOUtils.closeStream(writer);
    }

    @SuppressWarnings("deprecation")
    public static void read(String pathStr) throws IOException {
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(conf);
        Path path = new Path(pathStr);
        SequenceFile.Reader reader = new SequenceFile.Reader(fs, path, conf);

        Writable key = (Writable) ReflectionUtils.newInstance(reader.getKeyClass(), conf);
        Writable value = (Writable) ReflectionUtils.newInstance(reader.getValueClass(), conf);
        while (reader.next(key, value)) {
            System.out.printf("%s\t%s\n", key, value);
        }
        IOUtils.closeStream(reader);
    }

    public static void main(String[] args) throws IOException {
        write(output_path);
        read(output_path);
    }
}