存储系统实现-跳跃表实现索引检索
2013-05-26 11:43
127 查看
这一篇是我所实现的一个通过跳跃表的方式进行索引的检索。跳跃表的基本思路把单步检索扩展到多步检索,这样依赖减少检索的步骤来升性能。
先用一张流程图来阐述我检索的步骤。
读索引整体流程图:
这里举一个具体的例子来说一下检索的步骤。这里说一种检索到的情况,假设整个文件表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步才能检索到值,这样检索性能得到极大的提升。
下面把两代码代码给贴出来。
这个方法是一个私有方法,是一个递归方法,走步长的时候通过递归走步长。
总结:这里跳跃表的实现就写完了。欢迎大家拍砖
先用一张流程图来阐述我检索的步骤。
读索引整体流程图:
这里举一个具体的例子来说一下检索的步骤。这里说一种检索到的情况,假设整个文件表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步才能检索到值,这样检索性能得到极大的提升。
下面把两代码代码给贴出来。
/** * 先走一级步长,如果id>key,回退,走二级步长,id>key,一步一步走 * * @param id * @return */ public synchronized DataOffset read(int id) { DataOffset offset = getPosFromCache(id); if(offset!=null){ return offset; } long len; try { len = reader.length(); //如果长度大于两倍一级步长,先走一级步长 int key = goByStepLevel(len, 0, id, 0, stepLevel_1000); if (key != 0) { key = goByStepLevel(len, reader.getFilePointer(), id, 0, stepLevel_100); if (key != 0) { key = goByStepLevel(len, reader.getFilePointer(), id, 0, stepLevel_10); if (key != 0) { //直接走0级步长 System.out.println("[IndexFileReader.read]key="+key); key = goByStepLevel(len, reader.getFilePointer(), id, 0, skip); } } } System.out.println("[IndexFileReader.read]key2="+key); if (key == 0) { //拿到偏移量 reader.readInt(); offset = new DataOffset(); offset.setStartPos(reader.readLong()); //offset.setEndPos(reader.readLong()); //byte[] bytes = ByteUtil.longToByte(offset.getStartPos(),offset.getEndPos()); lruCache.put(indexPath + id, offset.getStartPos()); return offset; } } catch (IOException e) { e.printStackTrace(); } return null; }
这个方法是一个私有方法,是一个递归方法,走步长的时候通过递归走步长。
/** * @param len * @param nowStep * @param id * @param key * @param stepLevel * @return 1:代表值还在后面,0:代表该节点即为值,-1:值在前面 * @throws IOException */ private int goByStepLevel(long len, long nowStep, int id, int key, long stepLevel) throws IOException { //如果后面的步骤已经小于一级步长 if (len > nowStep + stepLevel) { //如果值仍然在后面,走一级步长 if (id > key) { nowStep = nowStep + stepLevel; reader.seek(nowStep); //这里已经读出一个值了,需要回退 key = reader.readInt(); return goByStepLevel(len, nowStep, id, key, stepLevel); } else if (id < key) { //退出,走二级步长 reader.seek(nowStep - stepLevel); return 1; } else { //相等,找到值直接定位到该值 reader.seek(nowStep); return 0; } } else { //如果值仍然在后面,走二级步长 if (id > key) { reader.seek(nowStep); return -1; } else if (id < key) { long preStep = nowStep - stepLevel; if (preStep > 0) { reader.seek(preStep); } else { //如果小于,则直接归0,走二级步长 reader.seek(0); } return 1; } else { //相等,如果找到值,直接seek到该偏移 reader.seek(nowStep); return 0; } } }
总结:这里跳跃表的实现就写完了。欢迎大家拍砖
相关文章推荐
- 存储系统实现-跳跃表实现索引检索
- Linux系统下实现iscsi共享存储
- ARM7系统中实现CF卡存储的文件系统设计
- SQL Server:使用系统存储过程实现的通用分页存储过程
- KWIC系统之事件架构实现(行存储类,行存储包装类,行存储改变事件)
- Android之数据存储共享参数实现系统设置操作功能(二)
- 现代IM系统中消息推送和存储架构的实现
- 云方案,依托H3C彩虹云存储架构,结合UIA统一认证系统,实现了用户数据的集中存储和管理
- 使用存储过程实现进销存系统中的先进先出算法(1)——数据库与存储过程设计
- 基于关系数据库系统链式存储的树型结构数据,求某结点下的子树所有结点算法(t-sql语言实现)
- 使用存储过程实现进销存系统中的先进先出算法(1)――数据库与存储过程设计
- JAVA实现简易的文件存储系统
- 存储系统的实现-探析存储的机制和原理
- 阿里云课程:云计算—分布式文件存储系统及实现
- (原创)基于关系数据库系统链式存储的树型结构数据,求某结点下的子树所有结点算法(t-sql语言实现)
- 数据库系统实现-辅助存储管理
- 如果系统要使用超大整数(超过long长度范围),请你设计一个数据结构来存储这种超大型数字以及设计一种算法来实现超大整数加法运算)
- wince应用程序(实现 获取存储设备的大小、实现 WINCE 系统重新启动、隐藏/显示 Windows 任务栏等等)【C#】
- 深入云存储系统Swift存储节点:存储实现分析