对于Hadoop将每个blob单独放在各自的文件中不能实现可扩展性,Hadoop为此开发了高层次容器
SequenceFile
sequencefile为二进制键值对提供了一个持久数据结构,比如将它作为日志文件的存储格式时,自己选择键的类型(可以是LongWritable类型的时间戳)和值的Writable类型(表示日志记录数量)
sequencefile也可以作为小文件的容器,HDFS和MR是针对大文件优化的,大量的小文件容易占用过多namenode的内存,可以通过sequencefile将小文件包装,后去更高效率的存储和处理,可以实现将若干个小文件打包成一个sequencefile类
1) 写操作
URI uri = new URI("hdfs://host/path");
Configutation conf = new Configuration();
String user = "user";
FileSystem fs = FileSystem.get(uri, conf);
Path path = new Path("hdfs://host/path");
LongWritable key = new LongWritable();
Text value = new Text();
SequenceFile.Writer writer = SequenceFile.createWriter(fs, conf, path, key.getClass(), value.getClass());
append(key, value)添加sequencefile内容
getLength()获取文件当前位置
2) 读操作
创建SequenceFIle.Reader实例不断调用next()方法迭代读取记录
//Writable类型 正确读取返回true,文件末尾返回false 使用反射工具类ReflectionUtils创建key value类型
public boolean next(Writable key, Writable value)
//非Writable类型 使用了其他序列化框架
public Object next(Object key) throws IOException
public Object getCurrentValue(Object val)throws IOException
同步点:数据读取迷路后能够再一次与记录边界同步的数据流中的某个位置,同步点是SequeneFile.Writer记录在顺序写入过程中插入一个特殊项,隔一些记录就有一个同步标识。特殊项很小,很小的存储开销,始终是在记录的边界处
public synchronized boolean syncSeen() 是否是顺序文件中同步点
public synchronized void seek(long position)搜索指定位置
public synchronized void sync(long position)定位到position之后的下一个同步点
命令行接口显示SequenceFile
-text选项
hadoop fs -text numbers.seq | header
SequenceFile的排序和合并
1) MapReduce
hadoop自带例子jar包中包含了按照指定键值类型将输入和输出指定为顺序文件
2)SequenceFile.Sorter类的sort()和merge(),更底层,没有MapReduce好
sequencefile的格式
文件头+一条或多条记录组成
文件头:前三个字节为SEQ(表示这是sequencefile,),第四个字节为版本号,之后是键值名称,数据压缩,用户定义元数据和同步标识
内部结构分为 未压缩 记录压缩 块压缩(多条记录压缩,不是128M数据块压缩)
记录长度 + 键长度 + 值长度 + 键 + 值
记录长度 + 键长度 + 值长度 + 键 + 压缩值
记录数目 + 块压缩键长度 + 块压缩键 + 块压缩值长度 + 块压缩值
MapFile
已经排序的SequenceFile,有索引,按键查找
索引本身是SequenceFile,包含map的小部分键
MapFile写操作时,map条目要顺序添加,否则IOException
MapFile变种
SetFile:存储Writable键的集合
ArrayFile:数组元素索引
BloomMapFile:get()对稀疏文件有用
其他文件格式
面向行的格式
SequenceFile
MapFile
Avro:面向大数据设计,紧凑可切分
Flume
面向列的格式
面向列对于访问表中一小部分你的查询比较有效,因为需要缓存切片,所以需要更多内存读写
Hive的ORCFile
Parquet
Avro的Trevni