在上一章當中,寫了文件的生成過程。這一章主要講解文件格式(V3版本)的具體細節。數組
字典文件的做用是在存儲的時候將字符串等類型轉換爲int類型,好處主要有兩點:ui
一、減小存儲佔用空間編碼
二、用在須要group by的字段上比較合適,能夠減小計算時的shuffle的數據量。spa
每個字典列都有對應的三種文件.dict, .sortindex, .dictmeta文件,輸出格式都是thrift格式code
字典的值每滿1000就做爲一個chunk輸出一次,具體的類是ColumnDictionaryChunkblog
相關參數:排序
carbon.dictionary.chunk.size索引
把字段的值sort了一下以後,計算出每一個值的sortIndex和invertedIndex,具體的類是ColumnSortInfoci
一、List<SortIndex>,記錄着每一個字典值的surrogate,從1開始字符串
二、List<SortInvertedIndex>,記錄着每一個字典surrogate在數組中的位置,從1開始
它們的關係以下:
sortIndex[i] = dictionarySortModel.getKey(); // the array index starts from 0 therefore -1 is done to avoid wastage // of 0th index in array and surrogate key starts from 1 there 1 is added to i // which is a counter starting from 0 sortIndexInverted[dictionarySortModel.getKey() - 1] = i + 1;
假設字典值是beijing,shenzhen,shanghai
城市 | surrogate | sortIndex | invertIndex |
beijing | 1 | 1 | 1 |
shenzhen | 2 | 3 | 3 |
shanghai | 3 | 2 | 2 |
該文件主要記錄字典的如下屬性,具體的類是ColumnDictionaryChunkMeta
一、最小key
二、最大的key
三、開始offset
四、結束offset
五、chunk的數量
CarbonRow在sort階段會被分紅3個部分:
一、字典列
二、非字典維度列和高基數列
三、度量值列
在寫入的時候,先寫入到TablePage裏,TablePage會把數據拆分紅4部分
// one vector to make it efficient for sorting private ColumnPage[] dictDimensionPages; private ColumnPage[] noDictDimensionPages; private ComplexColumnPage[] complexDimensionPages; private ColumnPage[] measurePages;
每一個TablePage都會記錄如下幾個Key:
private byte[][] currentNoDictionaryKey; // MDK start key private byte[] startKey; // MDK end key private byte[] endKey; // startkey for no dictionary columns private byte[][] noDictStartKey; // endkey for no diciotn private byte[][] noDictEndKey; // startkey for no dictionary columns after packing into one column private byte[] packedNoDictStartKey; // endkey for no dictionary columns after packing into one column private byte[] packedNoDictEndKey;
數據在一行一行寫到TablePage以後,最後會作一次統一的編碼,詳細的方法請看TablePage的encode方法。
Page的meta信息
private DataChunk2 buildPageMetadata(ColumnPage inputPage, byte[] encodedBytes) throws IOException { DataChunk2 dataChunk = new DataChunk2(); dataChunk.setData_page_length(encodedBytes.length); fillBasicFields(inputPage, dataChunk); fillNullBitSet(inputPage, dataChunk); fillEncoding(inputPage, dataChunk); fillMinMaxIndex(inputPage, dataChunk); fillLegacyFields(dataChunk); return dataChunk; }
一個blocket的閾值是64MB,一個blocket包括N個TablePage,當寫滿一個TablePage以後,就把blocket寫入到文件當中。
carbondata的BTree索引,是一個記錄着每一個Blocklet的mdk的startKey和endKey,以及Blocklet當中全部TablePage的列的最大最小值
那麼數據文件的詳細格式,基本和官網上介紹的是一致的
mdk和hbase的rowkey是一個性質的,詳細能夠看下面這張圖,排序方式跟hbase沒有任何區別。可是carbondata的mdk只能是字典列,若是我沒有設置字典列的話,只是設置了SORT_COLUMN,Carbondata的過濾只是靠列的最大最小值
索引文件以.carbonindex結尾
索引文件包括三個部分:索引頭,索引兩部分
索引頭包括:
一、文件格式版本(當前版本是V3)
二、Segment信息(有多少列,列的基數)
三、列的信息
四、bucket ID
索引信息包括如下信息:
一、Blocket的記錄數
二、數據文件名
三、Blocket的meta信息offset
三、BlockletIndex (BTree索引,包含blocket的startKey、endKey,以及每一列的最大最小值,這個前面已經講過了)
四、BlocketInfo(記錄數,每一個TablePage的offset,每一個TablePage的長度,維度列dimension_offsets的起始位置,度量值measure_offsets的起始位置,有多少個TablePagenumber_number_of_pages)
索引文件的信息在文件的footer當中也是存在的,在carbondata1.2當中索引文件仍是有不少個,感受有點多餘。
到carbondata1.3會被合併成一個文件,這樣就能大大縮短啓動的時候加載索引的開銷。
岑玉海
轉載請註明出處,謝謝!
個人博客即將搬運同步至騰訊雲+社區,邀請你們一同入駐:https://cloud.tencent.com/developer/support-plan