儲存系統實現-跳躍表實現索引檢索
這一篇是我所實現的一個通過跳躍表的方式進行索引的檢索。跳躍表的基本思路把單步檢索擴充套件到多步檢索,這樣依賴減少檢索的步驟來升效能。
先用一張流程圖來闡述我檢索的步驟。
讀索引整體流程圖:
這裡舉一個具體的例子來說一下檢索的步驟。這裡說一種檢索到的情況,假設整個檔案表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;
}
}
}
總結:這裡跳躍表的實現就寫完了。歡迎大家拍磚
相關文章
- 【Java】跳躍表的實現以及用例測試Java
- 【Redis】跳躍表原理分析與基本程式碼實現(java)RedisJava
- 基於ElasticSearch實現商品的全文檢索檢索Elasticsearch
- 實現報表資料分庫儲存
- Redis資料結構—跳躍表 skiplist 實現原始碼分析Redis資料結構原始碼
- 如何實現檔案傳輸系統的多儲存
- php + MongoDB + Sphinx 實現全文檢索PHPMongoDB
- 5分鐘瞭解Redis的內部實現跳躍表(skiplist)Redis
- ElasticSearch 實現分詞全文檢索 - 概述Elasticsearch分詞
- 使用LocalStorage實現Form表單內容本地儲存ORM
- 資料庫儲存與索引技術(三)LSM樹實現案例資料庫索引
- 作業系統——c++實現頁式虛擬儲存管理作業系統C++
- 如何快速實現高併發短文檢索
- InnoDB儲存引擎MVCC實現原理儲存引擎MVC
- vertica 如何實現儲存過程?儲存過程
- 帶貨直播系統,實現簡單的換頭像並儲存
- ElasticSearch 實現分詞全文檢索 - delete-by-queryElasticsearch分詞delete
- 線性表的順序儲存C++程式碼實現C++
- 跳錶實現
- 頭像點選檢視大圖和儲存功能實現(儲存的細節處理)
- abp(net core)+easyui+efcore實現倉儲管理系統——展現層實現增刪改查之列表檢視(七)UI
- 自研資料庫CynosDB儲存系統如何實現即時恢復資料庫
- innodb儲存引擎鎖的實現(一)儲存引擎
- 區塊鏈資訊儲存是如何實現安全儲存區塊鏈
- 如何把SQL Server中一個表,一個儲存過程,一個檢視等改為系統表,系統儲存過程,系統檢視等...SQLServer儲存過程
- Mysql 如何實現全文檢索,關鍵詞跑分MySql
- OpenCV特徵提取與影像檢索實現(附程式碼)OpenCV特徵
- 短視訊直播系統,動態內的圖片實現長按儲存
- abp(net core)+easyui+efcore實現倉儲管理系統——展現層實現增刪改查之增刪改檢視(八)UI
- 傳統資料庫也能實現區塊鏈儲存資料庫區塊鏈
- Kafka+Flink 實現準實時異常檢測系統Kafka
- 利用Kubernetes實現容器的持久化儲存持久化
- 使用 .NET 整合 MinIO 實現高效物件儲存物件
- RocketMQ 多級儲存設計與實現MQ
- 從零實現 k-v 儲存引擎儲存引擎
- 安卓實現賬號密碼儲存安卓密碼
- MySQL如何實現萬億級資料儲存?MySql
- redis 跳躍表Redis
- 大型系統儲存層遷移實踐