時序數據庫 Apache-IoTDB 源碼解析之元數據索引塊(六)

上一章聊到 TsFile 索引塊的詳細介紹,以及一個查詢所通過的步驟。詳情請見:node

時序數據庫 Apache-IoTDB 源碼解析之文件索引塊(五)git

打一波廣告,歡迎你們訪問 IoTDB 倉庫,求一波 Star 。歡迎關注頭條號:列炮緩開局,歡迎關注OSCHINA博客github

阿里雲、東方國信等各家公司正在招聘IoTDB數據庫開發工程師,歡迎加我微信內推:liutaohua001sql

這一章主要想聊聊:數據庫

  1. 原有索引中的不足
  2. 新版本中索引的設計

原有索引中的不足

如今來張圖回顧一下原有的數據存儲方式,在文件尾部使用DeviceMetaDataIndexMap和MeasurementSchemaMap中記錄全部設備數據偏移量、傳感器的相關信息等。由於使用的是Map結構訪問都是O(1)的,可是須要關注的一個問題就是它是在內存中O(1)的,在磁盤上並不能找到什麼好的查詢方式,惟一能作的就是所有讀取出來而後放到內存中。apache

一般狀況下這不會有什麼問題,可是使用在工業場景中,傳感器+設備頗有可能數以百萬計,這會引起不管你讀取的是一個傳感器或者是一個設備的數據,在DeviceMetaDataIndexMap這一段數據都須要完整的從磁盤上讀取回來,這好嗎?這很差,還拿以前的數據舉例:微信

時間戳 人名 體溫 ... 年齡
1580950800 張一 36.5 ... 30
1580950800 張二 36.9 ... 30
1580950800 張三 36.7 ... 30
1580950800 張.. 36.7 ... 30
1580950800 張兩百萬 36.7 ... 30

當執行一個查詢select 體溫 from 張三 where time = 1580950800 時,張1、張2、張三...張兩百萬這兩百萬個名字都須要從硬盤中讀取並反序列化出來(一般 IoTDB 中的路徑是root.T000100010002.A_JB01.JB01.JTJBGMCA6K2052561),也就是1999999個都是多餘的讀取。阿里雲

此外,在TsDeviceMetaDataList中,也是按照chunkGroup存儲,意味着,若是我僅查詢一列,一樣會把其它的列信息讀取出來。.net

新版本中索引的設計

爲了儘量貼近只讀投影列的思想,新版本中對於TsDeviceMetaDataList部分再也不按照設備級別存儲,改成按照傳感器級別存儲,TsFileMetaData部分再也不使用map存儲全部設備,改成使用多叉樹並有序排列設計

改動1: 使用將一個傳感器的全部ChunkMetaData的存儲在一塊兒,並使用TimeseriesMetadata結構進行維護(保存某個傳感器的開始的offset及數據長度),如圖:

改動2: 在完成改動1以後,咱們獲得了TimeSeriesMetadata-年齡,TimeSeriesMetadata-體溫, ..., TimeSeriesMetadata-x,在刷盤以前將全部TimeSeriesMetadata按照傳感器名字排序,那麼在這裏就能夠進行二分查找了,如圖:

改動3: 在一個複雜的設備上傳感器頗有可能多達數千個,例如:新能源汽車當中,每臺車量能夠多達4000多個信號項。假如咱們須要管理10萬輛車,那麼依然會有10萬 * 4000 = 4億個TimeSeriesMetadata。仍是太多了,假如咱們進行多個傳感器的值查詢時,每次都進行二分,這無疑是浪費的。

因此進行一個樹狀的提取,假設每1024個提取一次,那麼4億個能夠節省爲390,625個,假如再抽取一次,那就能夠減小到382個了,這樣咱們從硬盤上一次讀取1024個,最多讀取3次硬盤就能夠完成查找。大意如圖:

改動4: 除了傳感器以外,還要考慮的是設備級別,由於設備也是數以萬計,但同上面的邏輯是同樣的。再此就不進行贅述,如圖:

在代碼中使用MetadataIndexNode類進行存儲圖中的數據,表明了當前節點屬於管理設備的節點仍是管理傳感器的節點,是中間節點仍是葉子節點。使用MetadataIndexEntry用來存儲具體的信息,也就是TimeSeriesMetadata結構在硬盤上的偏移量或者子節點MetadataIndexNode在硬盤上的偏移量.

附上一個文件展現:

POSITION|	CONTENT
            -------- 	-------
                   0|	[magic head] TsFile
                   6|	[version number] 000002
|||||||||||||||||||||	[Chunk Group] of root.sg1.d1, num of Chunks:10000
                  12|	[Chunk] of s8289, numOfPoints:500, time range:[0,499], tsDataType:INT64, 
                     	startTime: 0 endTime: 499 count: 500 [minValue:1,maxValue:1,firstValue:1,lastValue:1,sumValue:500.0]
                    |		1 pages
                    		 ...
              350026|	[Chunk] of s0, numOfPoints:500, time range:[0,499], tsDataType:INT64, 
                     	startTime: 0 endTime: 499 count: 500 [minValue:1,maxValue:1,firstValue:1,lastValue:1,sumValue:500.0]
                    |		1 pages
                    		 ...
             1418902|	[Chunk Group Footer]
                    |		[marker] 0
                    |		[deviceID] root.sg1.d1
                    |		[dataSize] 1418890
                    |		[num of chunks] 10000
|||||||||||||||||||||	[Chunk Group] of root.sg1.d1 ends
             1418947|	[marker] 2
             1418948|	[ChunkMetadataList] of root.sg1.d1.s0, tsDataType:INT64
                    |		 [ChunkMetaData] of s0, offset:350026
                    		 ...
             2247838|	[TimeseriesMetadata] name:s0, offset:1418948, chunkMetaDataListDataSize:80
             3116728|	[MetadataIndexNode] nodeType:LEAF_MEASUREMENT, childSize:10
                    |		[MetadataIndexEntry] name:s0, offset:2247838, endOffset:2336808
                    |		[MetadataIndexEntry] name:s192, offset:2336808, endOffset:2425782
                    |		[MetadataIndexEntry] name:s2841, offset:2425782, endOffset:2514757
                    |		[MetadataIndexEntry] name:s3763, offset:2514757, endOffset:2603732
                    |		[MetadataIndexEntry] name:s4685, offset:2603732, endOffset:2692705
                    |		[MetadataIndexEntry] name:s5606, offset:2692705, endOffset:2781680
                    |		[MetadataIndexEntry] name:s6528, offset:2781680, endOffset:2870655
                    |		[MetadataIndexEntry] name:s745, offset:2870655, endOffset:2959629
                    |		[MetadataIndexEntry] name:s8371, offset:2959629, endOffset:3048604
                    |		[MetadataIndexEntry] name:s9293, offset:3048604, endOffset:3116728
             3116906|	[TsFileMetadata] deviceNums:1,chunkNums:10000,invalidChunkNums:0
                    |		[MetadataIndexNode] nodeType:INTERNAL_MEASUREMENT,childSize:1
                    |			[MetadataIndexEntry] name:root.sg1.d1,offset:3116728,endOffset:3116906
                    |		[bloom filter bit vector byte array length] 7794
                    |		[bloom filter bit vector byte array] 
                    |		[bloom filter number of bits] 62353
                    |		[bloom filter number of hash functions] 5
             3124764|	[TsFileMetadataSize] 7858
             3124768|	[magic tail] TsFile
             3124774|	END of TsFile

---------------------------------- TsFile Sketch End ----------------------------------

到此已經介紹完了文件的總體結構,以及索引的改進過程。

那麼一個sql是如何執行的呢,是怎樣進行的查詢?又是怎樣高速的寫入數據?

歡迎持續關注。。。。

相關文章
相關標籤/搜索