存储系统实现-跳跃表实现索引检索

文章转自:http://blog.csdn.net/luohuacanyue/article/details/8975957


        这一篇是我所实现的一个通过跳跃表的方式进行索引的检索。跳跃表的基本思路把单步检索扩展到多步检索,这样依赖减少检索的步骤来升性能。

       先用一张流程图来阐述我检索的步骤。

读索引整体流程图:

     这里举一个具体的例子来说一下检索的步骤。这里说一种检索到的情况,假设整个文件表10万条,id是连续自增,检索id=2312的值

     第一步:走缓存(这里是第一次检索肯定不能命中缓存)

     第二步:走千步长

         1)id=1000,小于2312,继续

                 2)id=2000,小于2312,继续

                 3)  id=3000,大于2312,回退到id=2000的值

   第三步:走百步长

                1)id=2100,小于2312,继续

                2)id=2200,小于2312,继续

                3)id=2300,小于2312,继续

                4)id=2400,大于2312,回退到id=2300的值

   第四步:走十步长

                1)id=2310,小于2312,继续

                2)id=2320,大于2312,回退到id=2310的值

  第五步:走单步长

                1)id=2311,小于2312,继续

                2)id=2312,等于2312,定位到该值,返回数据

      从这里可以看出检索这样一个值,最多只需要11步,如果缓存命中的话只需要一步就找到值,而如果顺序检索的话则需要2312步才能检索到值,这样检索性能得到极大的提升。

     下面把两代码代码给贴出来。

   

[java]  view plain copy
  1. /** 
  2.  * 先走一级步长,如果id>key,回退,走二级步长,id>key,一步一步走 
  3.  *  
  4.  * @param id 
  5.  * @return 
  6.  */  
  7. public synchronized DataOffset read(int id) {  
  8.     DataOffset offset = getPosFromCache(id);  
  9.     if(offset!=null){  
  10.         return offset;  
  11.     }  
  12.     long len;  
  13.     try {  
  14.         len = reader.length();  
  15.         //如果长度大于两倍一级步长,先走一级步长  
  16.         int key = goByStepLevel(len, 0, id, 0, stepLevel_1000);  
  17.         if (key != 0) {  
  18.             key = goByStepLevel(len, reader.getFilePointer(), id, 0, stepLevel_100);  
  19.             if (key != 0) {  
  20.                 key = goByStepLevel(len, reader.getFilePointer(), id, 0, stepLevel_10);  
  21.                 if (key != 0) {  
  22.                     //直接走0级步长  
  23.                     System.out.println("[IndexFileReader.read]key="+key);  
  24.                     key = goByStepLevel(len, reader.getFilePointer(), id, 0, skip);  
  25.                 }  
  26.             }  
  27.         }  
  28.         System.out.println("[IndexFileReader.read]key2="+key);  
  29.         if (key == 0) {  
  30.             //拿到偏移量  
  31.             reader.readInt();  
  32.             offset = new DataOffset();  
  33.             offset.setStartPos(reader.readLong());  
  34.             //offset.setEndPos(reader.readLong());  
  35.             //byte[] bytes = ByteUtil.longToByte(offset.getStartPos(),offset.getEndPos());  
  36.             lruCache.put(indexPath + id, offset.getStartPos());  
  37.             return offset;  
  38.         }  
  39.     } catch (IOException e) {  
  40.         e.printStackTrace();  
  41.     }  
  42.     return null;  
  43. }  


这个方法是一个私有方法,是一个递归方法,走步长的时候通过递归走步长。

[java]  view plain copy
  1. /** 
  2.  * @param len 
  3.  * @param nowStep 
  4.  * @param id 
  5.  * @param key 
  6.  * @param stepLevel 
  7.  * @return 1:代表值还在后面,0:代表该节点即为值,-1:值在前面 
  8.  * @throws IOException 
  9.  */  
  10. private int goByStepLevel(long len, long nowStep, int id, int key, long stepLevel)  
  11.         throws IOException {  
  12.     //如果后面的步骤已经小于一级步长  
  13.     if (len > nowStep + stepLevel) {  
  14.         //如果值仍然在后面,走一级步长  
  15.         if (id > key) {  
  16.             nowStep = nowStep + stepLevel;  
  17.             reader.seek(nowStep);  
  18.             //这里已经读出一个值了,需要回退  
  19.             key = reader.readInt();  
  20.             return goByStepLevel(len, nowStep, id, key, stepLevel);  
  21.         } else if (id < key) {  
  22.             //退出,走二级步长  
  23.             reader.seek(nowStep - stepLevel);  
  24.             return 1;  
  25.         } else {  
  26.             //相等,找到值直接定位到该值  
  27.             reader.seek(nowStep);  
  28.             return 0;  
  29.         }  
  30.     } else {  
  31.         //如果值仍然在后面,走二级步长  
  32.         if (id > key) {  
  33.             reader.seek(nowStep);  
  34.             return -1;  
  35.         } else if (id < key) {  
  36.             long preStep = nowStep - stepLevel;  
  37.             if (preStep > 0) {  
  38.                 reader.seek(preStep);  
  39.             } else {  
  40.                 //如果小于,则直接归0,走二级步长  
  41.                 reader.seek(0);  
  42.             }  
  43.             return 1;  
  44.         } else {  
  45.             //相等,如果找到值,直接seek到该偏移  
  46.             reader.seek(nowStep);  
  47.             return 0;  
  48.         }  
  49.     }  
  50. }  

总结:这里跳跃表的实现就写完了。欢迎大家拍砖

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值