本文在Hive-ORC文件存儲格式的理論基礎上,進一步分析一個實際的Hive ORC表中的數據存儲形式。markdown
庫名+表名:fileformat.test_orc編碼
字段 | 類型 |
---|---|
category_id | string |
product_id | int |
brand_id | int |
price | double |
category_id_2 | string |
在hive中命令desc formatted fileformat.test_orc;
的結果以下圖:
根據上圖中的location信息,查看在HDFS上的文件:
.net
hive提供了一個--orcfiledump
參數用於查看HDFS上ORC表格的文件信息,在hive-0.13版本中的使用方法爲:hive --orcfiledump <location-of-orc-file>
,其餘版本的使用方法能夠去官方文檔中查找。
下面是命令hive --orcfiledump /user/hive/warehouse/fileformat.db/test_orc/000000_0
的查詢結果
code
接下來的分析,請對照着文章Hive-ORC文件存儲格式中的圖1-ORC文件結構圖進行。
使用hql語句,統計出各字段的count, min, max, sum信息以下:orm
字段 | COUNT | MIN | MAX | SUM |
---|---|---|---|---|
category_id | 1000000 | 5011 | 975673 | 4.0222868968E11 |
product_id | 1000000 | 968 | 50997770 | 27158964508399 |
brand_id | 999130 | 0 | 1026427 | 774991825568 |
price | 1000000 | -0.0092 | 358000.0 | 1.8953626711045265E8 |
category_id_2 | 1000000 | 5010 | 5996 | 5.183530839E9 |
從dump文件的圖片中能夠看出,大體分紅四個部分:blog
記錄整張表的記錄數,壓縮方式,壓縮大小,以及表結構。在表結構部分,ORC將整張表的全部字段構形成一個大的struct結構。對應圖1-ORC文件結構圖中的Postscript部分。圖片
統計當前HDFS文件對應Stripe的信息,包括各個字段的count,min, max, sum信息。對於最外層的Struct,只統計其count值。因爲這張表數據量不大,當前HDFS文件中只有一個Stripe。對應圖1-ORC文件結構圖中的Stripe Footer部分。
ip
統計內容和第二部分一致,不過這裏統計的整張表的每一個字段count, min, max, sum信息。對應圖1-ORC文件結構圖中的FileFooter部分。
這裏咱們將dump文件中的統計信息,與各字段實際統計信息做對比。經過與上面表格中各字段統計信息對比,發現對於int類型和double類型的字段,min, max, sum的結果都是匹配的。可是對於string類型的字段,僅僅只有min, max統計結果一致,sum的結果不相同。文檔
統計各Stripe的offset,總記錄行數等Stripe層次的信息。該Stripe中各字段的Index Data和Row Data,以及每一個字段的編碼方式。
前面一行Stripe: offset: 3 data: 7847351 rows: 1000000 tail: 132 index: 7936應該也是保存在FileFooter中,後面各個字段統計信息對應圖1-ORC文件結構圖中的Index Data和Row Data部分。
從dump文件中的數據能夠看出,每一個字段的ROW_INDEX以及DATA信息是保存在一塊連續空間中的,這塊文件從offset=3開始。這也說明圖1-ORC文件結構圖中Row Data區的數據緊隨Index Data區數據以後。
Index Data數據統計:get
起始位置 | 字段 |
---|---|
3……21 | STRUCT |
22……1141 | category_id |
1142……3056 | product_id |
3057……5135 | brand_id |
5136……7201 | price |
7202……7938 | category_id_2 |
Row Data數據統計:
起始位置 | 字段 | 描述 |
---|---|---|
7939……59887 | category_id | 字段對應詞條int流 |
59888……59898 | category_id | 詞條長度int流 |
59899……60989 | category_id | 字典詞條數據 |
60990……3525432 | product_id | 實際數據int流 |
3525433……3527085 | brand_id | 標識IF NULL的byte流 |
3527086……5708142 | brand_id | 實際數據int流 |
5708143……7855016 | price | double類型 |
7855017……7855212 | category_id_2 | 字段對應詞條int流 |
7855213……7855219 | category_id_2 | 詞條長度int流 |
7855220……7855289 | category_id_2 | 字典詞條數據 |
在ORC文件的int類型和string類型保存時,會有一個byte流用於記錄字段的某個記錄是否爲null,根據統計只有brand_id 字段的count值不足100000條,也就是說除了brand_id 字段以外,其餘字段中沒有null值。因此在上面Row Data表中,只有brand_id有一個對應的IF NULL標識流。一個String類型,會將詞條數據保存在字節流中,而後一個int流記錄每一個詞條的長度,另一個int流用於指定字段某個記錄對應字典詞條中的哪個。
這部分最後記錄了每個字段的存儲方式,統計以下
字段 | 類型 | 存儲方式 |
---|---|---|
STRUCT | DIRECT | |
category_id | String | DICTIONARY_V2 |
product_id | Int | DIRECT_V2 |
brand_id | Int | DIRECT_V2 |
price | Double | DIRECT |
category_id_2 | String | DICTIONARY_V2 |