关于HFile的思考
0.90.x版本的HBase中的文件是存储在HFile中的。
关于HFile文件的详细介绍,可以查看这篇文章:http://www.data-works.org/download/hfile.pdf
这篇文章中介绍了以下五点内容:
- HFile的作用。
- HFile的格式。
- HFile的性能。
- HFile的使用注意事项。
- HFile的编程接口。
HFile中有一个很重要的参数,那就是block size。如果我们写入hfile中的某一个value的值大于block size会怎么样?
于是有如下的测试代码:
1: // create local file system
2: FileSystem fs = new RawLocalFileSystem();
3: fs.setConf(new Configuration());
4:
5: // block size = 1kb
6: HFile.Writer hwriter = new HFile.Writer(fs,
7: new Path("hfile"), 1, (Compression.Algorithm) null, null);
8:
9: // create key & value, the value is 8kb, larger than 1kb
10: byte[] key = "www.data-works.org".getBytes();
11: byte[] value = new byte[8 * 1024];
12: for (int i = 0; i < 8 * 1024; i++) {
13: value[i] = '0';
14: }
15:
16: // add values to hfile
17: for (int i = 0; i < 10; i++) {
18: hwriter.append(key, value);
19: }
20:
21: // close hfile
22: hwriter.close();
上面的代码可以看出来,每一个value的值都是8kb,已经超过了hfile预设的1kb的block size。
实际的写入情况是如果value大于block size,那么就按照实际的情况来写。
上面的测试用例执行完毕以后,整个hile文件只有1个data block。
这个hfile的读取代码如下:
1: // create local file system
2: FileSystem fs = new RawLocalFileSystem();
3: fs.initialize(URI.create("file:///"), new Configuration());
4: fs.setConf(new Configuration());
5: HFile.Reader hreader = new HFile.Reader(fs,
6: new Path("hfile"), null, false);
7:
8: // loadFileInfo
9: hreader.loadFileInfo();
10:
11: HFileScanner hscanner = hreader.getScanner(false, false);
12:
13: // seek to the start position of the hfile.
14: hscanner.seekTo();
15:
16: // print values.
17: int index = 1;
18: while (hscanner.next()) {
19: System.out.println("index: " + index++);
20: System.out.println("key: " + hscanner.getKeyString());
21: System.out.println("value: " + hscanner.getValueString());
22: }
23:
24: // close hfile.
25: hreader.close();
上面的代码将读取hfile,并将这个文件中的所有kv打印出来。
通过上面的测试可以看出:如果某一个key有非常非常多的value,那么查找这些value就无法通过索引去快速查找,而是需要通过遍历进行。
另外,JIRA上面的HBASE-3857也提出了一种新的HFile格式,HFile v2
他主要是针对现有HFile的两个主要缺陷提出来的:
- 暂用过多内存
- 启动加载时间缓慢
有兴趣的朋友可以详细了解一下。
更多关于HBase方面的文章,请参考:http://blog.data-works.org