數據庫索引對於數據查詢的重要性不可言喻,所以做者在存儲層實現了二級索引,以及利用索引進行掃描的功能。目前僅實現了分區表與非分區表的本地索引(數據與索引共用一個Raft組管理),全局索引及反向索引待之後再實現。數據庫
1、存儲結構:在介紹索引前先了解一下數據與索引是以何種結構存儲於RocksDB內的,每一個節點的RocksDB實例都包含如下兩個ColumnFamily,每一個列簇的存儲結構以下:api
TableId(with OrderFlag) | EntityId |
---|---|
32bit | 128bit |
Versions | GC Flag | [VersionTS + DataPtr] | [Data [FieldId + Value]] |
---|---|---|---|
15bit | 1 bit | Versions * (64+32bit) | Versions * nbit |
TableId | IndexId | IndexKey Values | None unique index's EntityId |
---|---|---|---|
32bit | 8bit | [FieldId + Value] | 128bit |
與TableCF的Value編碼相同。異步
在新建實體模型及修改實體模型時都可添加與刪除索引(以下圖所示),須要注意的是修改模型時添刪索引會啓用異步任務變動表結構並重建索引數據(請參考以前的文章:異步結構變動),若是是重建唯一索引可能失敗,在實體模型設計器內可查看索引重建狀態。在索引重建過程當中或重建失敗後利用索引掃描數據會直接報錯,告知索引還沒有準備好。async
不一樣於傳統Sql數據庫解析Sql後利用索引掃描,服務模型的代碼必須明確指定用哪一個索引來查詢數據,具體參考如下示例代碼如何利用索引掃描數據:ide
public async TaskIndexScan() { //新建索引掃描,範型參數1爲實體類型,參數2爲索引類型 var q = new IndexScan(); //若是是分區表可經過分區謂詞指定分區掃描,非分區表無效 q.Partitions.Equal(t => t.VID, 3); //可指定索引謂詞肯定掃描範圍 q.Keys.Equal(t => t.VID, 3); //若是是複合索引可指定其餘索引謂詞 q.Keys.Equal(t => t.Speed, 100); return await q.Take(10).ToListAsync(); }
- 索引謂詞目前僅實現了相等性判斷,其餘如大於、小於等稍後實現
- 索引掃描的附加過濾條件還沒有實現
另若是須要插入一批測試數據可參考如下示例代碼:工具
public async TaskFillData() { //第一個參數128表示並行任務數,第二個參數表示每一個任務執行次數 //做者虛擬機(I74C8G)執行如下代碼約每秒插入13000條記錄 return await SimplePerfTest.Run(128, 500, async (i, j) => { var obj = new Entities.VehicleState(i); obj.Speed = j; await EntityStore.SaveAsync(obj); }); }4、本篇小結:
本篇介紹數據及索引的存儲結構以及利用索引掃描api來查詢數據,下一步做者將實現其餘謂詞條件,另外實現聚合掃描並優化單分區事務遞交。GitHub上的運行時已更新(包括dbscan工具)可供測試。若是您有問題或Bug報告,請留言或提交Issue,另外您的關注與點贊將是做者最大的動力。測試