2)整個數據塊由壹個或多個鍵值組成。
3)在文件中按關鍵字排序。
這裏只介紹V2版本。HFileV1的數據格式已從0.92版本升級到V2版本。
1)文件分為三部分:掃描塊部分、非掃描塊部分和打開時數據部分。
Scanned block section:表示順序掃描HFile時(包括所有要讀取的數據),將讀取所有數據塊,包括Leaf索引塊和Bloom塊;;
非掃描塊部分:HFILE順序掃描時不會讀取這部分數據,主要包括兩部分:Meta塊,即BloomFilter和中間層數據索引塊;
Load-on-open-section:這部分數據需要在HBase的區域服務器啟動時加載到內存中。包括FileInfo、Bloom filter塊、數據塊索引和元塊索引;;
Trailer:這部分主要記錄了HFile的基本信息、各部分的偏移量值以及尋址信息。
葉索引塊專門存儲數據塊的偏移量、長度和第壹鍵信息。
RootDataIndex存儲每個葉索引塊記錄的偏移量、長度、第壹個鍵以及記錄到該葉索引塊的數據塊數量。
假設DataBlock的數量足夠多,並且HFile文件足夠大,那麽長度為128KB的默認ROOTDataIndex在仍然超過區塊大小時將被分成更多層。這最終可能是根索引-& gt;中級根索引(可以是多層的)-》葉索引塊
對應於Mid鍵的信息將被記錄在根索引中,這有助於在進行文件拆分或半查詢時快速定位中間行的信息。
V2文件的寫操作流程:
1)將KV附加到數據塊。在每次追加之前,首先檢查當前數據塊的大小是否超過默認設置,如果沒有超過閾值,則將其寫入輸出流。如果超過閾值,則執行finishBlock(),並根據Table-CF的設置對數據塊進行編碼和壓縮,然後寫入HFile。//分塊編碼和壓縮時會有壹些性能開銷。請參考HBase實戰系列1-壓縮編碼技術。
2)根據數據的大小,寫入葉子索引塊和Bloom塊。
葉索引塊。每次數據塊刷新時,都會向塊中添加壹條記錄,並判斷塊的大小是否超過閾值(默認為128KB)。如果超過閾值,將在數據塊之後寫入葉索引塊。對應的控件類:HFileBlockIndex,內置了BlockIndexChunk、BlockIndexReader和BlockIndexWriter(實現了InlineBlockWriter接口)。
Bloom Block設置:默認使用brunh哈希策略,每個Block的默認大小為128KB。每個BloomBlock可以接收的密鑰數量由以下公式計算得出,接收的密鑰數量與Block的容量和錯誤率之間存在壹定的關系。在下面的計算公式中,可以得出每個BloomBlock默認可以接受109396個密鑰的結論。
註意:影響BloomBlock數量的因素明顯受到HFile中KeyValue、errorRate和BlockSize的數量的影響。相關控制參數可以根據應用的要求進行合理調整。
每個數據塊將對應於索引信息,並存儲在元索引區域中。
這樣,在加載數據時,只需要加載不超過128KB的RootDataIndex和IntermediateLevelRootIndex,避免加載HFile V1等所有葉索引塊信息。同樣,您只需要將BloomBlockIndex信息加載到內存中。這樣就避免了加載HFile V1格式的過大DataBlockIndex帶來的開銷,加快了Region的加載速度。
根據文件中的關鍵字搜索數據的過程:
1.首先在內存中搜索HFile的根索引。如果支持多級索引,則定位葉/中間索引;如果支持單級索引,則定位數據塊。
2.如果支持多級索引,將從緩存/hdfs(分布式文件系統)中讀取葉/中間索引塊,並根據鍵值在葉/中間塊中執行二分搜索法(葉/中間索引塊支持二分搜索法)以找到相應的數據塊。
3.從緩存/hdfs讀取數據塊。
4.遍歷數據塊以找到鍵。
1.首先讀取文件末尾的4字節版本信息(FileTrailer的版本字段)。
2.根據版本信息獲取trailer的長度(不同版本長度不同),然後根據Trailer的長度加載FileTrailer。
3.將打開時加載部分加載到內存中。初始文件偏移地址為trailer中的loadOnOpenDataOffset,打開時加載部分的長度等於(HFile文件長度-HFileTrailer長度)。
打開加載各部分的加載順序如下:
依次加載每個部分的HFileBlock(load-on-open的所有部分都以HFileBlock格式存儲):數據索引塊、元索引塊、FileInfo塊、生成布隆過濾器索引和刪除布隆過濾器。下面將介紹HFileBlock的格式。
在hfile中,所有索引和數據都以HFileBlock的格式存在於hdfs中。
HFile版本2的塊格式如下圖所示。有兩種類型。第壹種類型是沒有校驗和;。第二是包括校驗和。對於block,下圖中綠色和淺綠色的內存是塊頭;;深紅色部分是塊數據;;粉色部分是校驗和。
第壹塊的頭長度= 8+2 * 4+8;
第二個塊的頭長度= 8+2 * 4+8+1+4 * 2;
區塊類型:8字節的魔術,代表不同的區塊類型。
CompressedBlockSize:表示壓縮的塊數據大小(即HDFS中的HFileBlock數據長度),不包括標頭長度。
UncompressedBlockSize:表示未壓縮的塊數據大小,不包括頭長度。
preblock offset:hfile中前壹個塊的偏移地址;用於訪問前壹個塊而不跳轉到前壹個塊,實現類似鏈表的功能。
校驗和類型:在支持塊校驗和中,指示校驗和的類型。
BytePerCheckSum:在支持CheckSum的塊中,記錄checksumChunk中的字節數;記錄校驗和塊中的字節數。
SizeDataOnDisk:在支持checksum的塊中,記錄了該塊在磁盤中的數據大小,不包括checksumChunk。
DataBlock是用於存儲特定kv數據的塊,其格式比index和meta(這裏的meta指bloom filter)的格式簡單。
在DataBlock中,KeyValue的分布如下所示,後跟壹個時間戳。
HFile中的索引級別不是固定的,根據不同的數據類型和數據大小有不同的選擇。主要有兩類,壹類是單級索引,另壹類是多級索引,因此索引塊無法存儲在內存中,因此采用多級索引。
HFile中有兩類索引塊,即根索引塊和非根索引塊。非根索引塊分為中間索引塊和葉索引塊,但元數據索引塊和葉索引塊在內存中的分布是相同的。
對於元塊和布隆塊,索引采用單級形式。當使用單級時,只使用根索引塊來保存指向塊的索引信息(根索引-》XXX塊)。
對於數據,當HFile中的數據塊數量較小時,單個級別(root _ index-》;數據塊)。當數據塊數量較大時,采用多級索引,壹般為兩級索引,用根索引塊和葉索引塊保存索引信息(root _ index-》leaf _ index-》;data _ block);但當數據塊數量較大時,采用三級索引,使用根索引塊、元數據索引塊和葉索引塊來保存指向數據的索引(root _ index-》;中間索引-》;leaf _ index-& gt;數據塊)。
所有索引塊都以HFileBlock格式存儲,首先是HFileBlock頭,然後是索引塊的內容。
根索引適用於兩種情況:
1,作為數據索引的根索引。
2.作為meta和bloom的索引。
在Hfile版本2中,元索引和布隆索引都是單級的,並且都是根索引的格式。數據索引可以是單級和多級的形式根索引可以表示單級索引或多級第壹級。然而,這兩種表示以某種方式存儲在內存中,如圖所示。
對於多級根索引,除了上面的索引條目數組外,還有關於數據中間鍵的額外信息,用於在拆分hfile時快速定位HFile的中間位置。硬盤多級根索引的格式如圖3.4所示。
Mid-key的信息組成如下:
1,Offset:葉索引塊的起始偏移量。
2.磁盤大小:葉索引塊的長度。
3.鍵:葉索引塊中的位置。