<文件开头>
[数据块 1]
[数据块 2]
...
[数据块 N]
[元数据块 1]
...
[元数据块 K]
[元数据索引块]
[数据索引块]
[脚注] (固定大小; 偏移量为文件大小减去脚注大小)
<文件结束>
文件包含内部的指针. 每个指针可以用BlockHandle
来表示, 包含以下信息
offset: varint64
size: varint64
varint64
格式的说明请参考protocol-bufers/varints.
-
key-value键值对序列被有序地分区存储在一系列的数据块中. 这些数据块从文件起始相继被存储. 每个数据块根据
block_builder.cc
的代码对key-value键值对进行编码, 并且有选择地被压缩. -
我们在数据块后存储了一些元数据块. 目前被支持的元数据块类型在下面会得到详细说明, 更多的类型可能在未来得到支持. 每个元数据块也使用
block_builder.cc
进行编码, 并且有选择地被压缩. -
元数据索引块为每一个元数据块创建一条
key-value
键值对,key
是元数据块的名字,value
是指向元数据块的内部指针. -
数据索引块为每一个数据块创建一条
key-value
键值对,key
在区间[last_key of current data block, first_key of successive data block)
内, 取最短, value是指向数据块的内部指针. -
文件尾部是一个固定长度的脚注, 包含了元数据索引块和数据索引块的
BlockHandle
以及一个magic number
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)
filter元数据块
如果数据库被创建时指定了FilterPolicy
选项, 那么每一个table
文件都会存储一个对应的filter元数据块. 而元数据索引块就会包含一条key-value键值对, key = "filter.<Name of FilterPolicy>"
, value
为指向filter block
的内部指针.
filter block存储了一系列的filters
, filters_i
是FilterPolicy::CreateFilter()
在某一数据块所有key作为输入时的输出, 该数据块在文件的偏移量落在区间[i * base, (i + 1) * base)
内.
目前的base
设置为2KB
. 举例来说, 如果块X
和块Y
都在区间[i * base, (i + 1) * base - 1)
内, 则块X
和块Y
的所有key
都被转换到filter block的第i
个filter
.
filter block的格式如下:
[filter 0]
[filter 1]
[filter 2]
...
[filter N-1]
[offset of filter 0] : 4 bytes
[offset of filter 1] : 4 bytes
[offset of filter 2] : 4 bytes
...
[offset of filter N-1] : 4 bytes
[offset of beginning of offset array] : 4 bytes
lg(base) : 1 byte
filter block尾部的offset array
提供了一个高效的从数据块偏移量到对应的filter
的映射.