首页 > 代码库 > Tair LDB基于Prefixkey的范围查找性能优化项目提议方案

Tair LDB基于Prefixkey的范围查找性能优化项目提议方案

基于prefix bloomfilter的过滤思想和get_range接口数据的特点,在导师的指导下,提出如下的简单方案,对get_range接口的范围查找过程进行优化,使得能够根据prefix进行过滤,减少无效的磁盘IO。

待优化接口

int get_range(int area, const data_entry &pkey, const data_entry &start_key,   
    const data_entry &end_key, int offset, int limit, vector<data_entry*> 
    &values,shorttype=CMD_RANGE_ALL);


提议方案

1.   由于get_range接口的数据是从prefix_put/prefix_incr接口进来的,那么prefix的长度信息就可以从它们的pkey参数得到,pkey的数据类型是data_entry,有属性prefix_size,那么我们在客户端将pkey和skey合并为mkey(已经设置mkey的prefix_size为pkey的size)后与value一起传送到服务器端。

在客户端与服务器端的连接过程中,将key的类型封装成LdbKey类,value的类型封装成LdbItem类,LdbItem里面含有key的prefix_size信息,然后两者都转化为Slice类型发送到leveldb底层进行存储操作。注意此时value里面包含了prefix_szie信息(序列化信息,不能直接提取),因此我们在生成filter block时可以从value中提取出prefix_size信息(按LdbItem的格式进行分析提取)以生成我们所需要的prefix bloomfilter。提取的具体实现可以放在leveldb层的外面,在leveldb里面进行调用即可(分离操作)。

 

2. 提取到prefix_size信息后,我们 对所有的keys实现prefix bloomfilter,为了实现简单,我们可以在原有的filter block里加入新的prefix bloomfilter,与现有的bloomfilter一起存放,方法也很简单,就是在原有的filter block building过程中(filter_block.cc),将key的prefix也当作普通的key一起加入filter中,两者的过滤算法也是一致的。

注:目前filter的创建是每添加一个key,filter就会增大bits_per_key_个位,但由于一部分keys的prefix是相同的,也不会重复添加进filter,因此最终增加的bits应该可以接受。

 

3. 在get_range接口中,如果查找到了sstable这里(先查memtable和immutable memtable,两者没有磁盘IO操作),

(1)首先根据[pkey+skey,pkey+end]的范围查找可能的sstfiles。

(2)对于每一个file,对dataindex block里的信息继续进行范围查找,找到可能包含[pkey+skey,pkey+end]这个范围的blocks。

(3)在读每一个block之前,获取filter block中存储的filter,通过prefix的MayMatch方法判断该block是否包含前缀pkey,如果不包含,则直接跳过这个block,这样就通过prefix bloomfilter实现了block过滤,从而减少了不必要的磁盘IO操作。


关于get_range接口目前的实现方法可以参考:

tair中对get/get_range接口的理解及为get_range添加命令行测试接口