leveldb表文件格式
赵星宇
本文介绍leveldb的表文件格式。leveldb的表文件是不可变的,一旦形成就不可以修改。下面介绍其布局:
<文件开始>
[数据块 1]
[数据块 2]
...
[数据块 N]
[meta块 1]
...
[meta块 K]
[meta索引块]
[索引块]
[Footer](固定大小; 其开始位置为:文件大小-Footer大小)
<文件结束>
名词介绍:
数据块:存放实际kv对数据的块。
meta块:存放元数据的块,其分为filter块和统计信息块,目前统计信息块还没有实现,所以目前meta块==filter块。
meta索引块:存放meta块名字即key和meta块开始位置和长度即value的kv对数据的块。
索引快:存放每个数据块起始key和数据块开始位置和长度的即value的kv对数据的块。
Footer:固定大小,其开始位置为:文件大小-Footer大小,存放meta索引块和索引块的开始位置和长度。
Footer布局:
metaindex_handle: char[p]; // Block handle for metaindex
index_handle: char[q]; // Block handle for index
padding: char[40-p-q]; // zeroed bytes to make fixed length
// (40==2*BlockHandle::kMaxEncodedLength)
magic: fixed64; // == 0xdb4775248b80fb57 (little-endian)
可以看出其中存放了meta索引块的开始位置和长度、索引块的开始位置和长度。
filter(bloom filter)块布局:
[filter 0]
[filter 1]
[filter 2]
...
[filter N-1]
[filter 0的偏移量] : 4 bytes
[filter 1的偏移量] : 4 bytes
[filter 2的偏移量] : 4 bytes
...
[filter N-1的偏移量] : 4 bytes
[filter偏移量数组的起始位置] : 4 bytes
lg(base) : 1 byte
可以看出一个filter块中会存很多filter,而且一般来说filter块只会有一个。
base表示数据块起始位置映射到filter号时需要除的偏移量。
数据块起始位置除以base就是其对应的filter号。
GET数据过程分析:(很多其实缓存在内存中不用去文件里面读)
GET数据时,首先根据文件大小和Footer的固定大小,找到Footer信息,解析出其中保存的meta索引块的开始位置和长度、索引块的开始位置和长度。并且据此读取出meta索引块和索引块,并根据meta索引块中的信息将filter块读取出来。根据索引块可以找到get的key对应的数据块偏移量。利用这个偏移量计算对应的filter号,找到filter后可以做bloom判断,如果不存在则不用读取数据块,如果存在则读取数据块从中读取数据。