block结构示意图
sstable中Block 头文件如下:
class Block { public: // Initialize the block with the specified contents. // Takes ownership of data[] and will delete[] it when done. Block(const char* data, size_t size); ~Block(); size_t size() const { return size_; } Iterator* NewIterator(const Comparator* comparator); private: uint32_t NumRestarts() const; const char* data_; size_t size_; uint32_t restart_offset_; // Offset in data_ of restart array // No copying allowed Block(const Block&); void operator=(const Block&); class Iter; };
重启点在上个章节已经介绍过了
"“重启点”是干什么的呢?简单来说就是进行数据压缩,减少存储空间。我们一再强调,Block内容里的KV记录是按照Key大小有序的,这样的话,相邻的两条记录很可能Key部分存在重叠,比如key i=“the car”,Key i+1=“the color”,那么两者存在重叠部分“the c”,为了减少Key的存储量,Key i+1可以只存储和上一条Key不同的部分“olor”,两者的共同部分从Key i中可以获得。记录的Key在Block内容部分就是这么存储的,主要目的是减少存储开销。“重启点”的意思是:在这条记录开始,不再采取只记载不同的Key部分,而是重新记录所有的Key值,假设Key i+1是一个重启点,那么Key里面会完整存储“the color”,而不是采用简略的“olor”方式。但是如果记录条数比较多,随机访问一条记录,需要从头开始一直解析才行,这样也产生很大的开销,所以设置了多个重启点,Block尾部就是指出哪些记录是这些重启点的。 "
//获取BLOCK中的重启点数目 inline uint32_t Block::NumRestarts() const { assert(size_ >= 2*sizeof(uint32_t)); return DecodeFixed32(data_ + size_ - sizeof(uint32_t)); //重启点在block最后8字节(uint32_t)中
}
Block的创建和销毁
Block::Block(const char* data, size_t size) : data_(data), size_(size) { if (size_ < sizeof(uint32_t)) { size_ = 0; // Error marker } else { restart_offset_ = size_ - (1 + NumRestarts()) * sizeof(uint32_t); //重启点数目1个uint32 每个重启点的偏移记录 uint32 合记共(1+NumRestarts())* sizeof(uint32_t) if (restart_offset_ > size_ - sizeof(uint32_t)) { // The size is too small for NumRestarts() and therefore // restart_offset_ wrapped around. size_ = 0; } } } Block::~Block() { delete[] data_; }
Block中每个entry的解码
entry结构如上图的 KeyValuePair
static inline const char* DecodeEntry(const char* p, const char* limit, uint32_t* shared, uint32_t* non_shared, uint32_t* value_length) { if (limit - p < 3) return NULL; //至少包含3个 共享字节 *shared = reinterpret_cast<const unsigned char*>(p)[0]; *non_shared = reinterpret_cast<const unsigned char*>(p)[1]; *value_length = reinterpret_cast<const unsigned char*>(p)[2]; if ((*shared | *non_shared | *value_length) < 128) { // Fast path: all three values are encoded in one byte each p += 3; } else { if ((p = GetVarint32Ptr(p, limit, shared)) == NULL) return NULL; if ((p = GetVarint32Ptr(p, limit, non_shared)) == NULL) return NULL; if ((p = GetVarint32Ptr(p, limit, value_length)) == NULL) return NULL; } if (static_cast<uint32_t>(limit - p) < (*non_shared + *value_length)) { return NULL; } return p; }
参考:
https://www.cnblogs.com/itdef/p/9789620.html