orcFile split和讀資料原理總結(hive0.13)
阿新 • • 發佈:2019-02-08
背景
Hive的rcfile格式已經使用多年,但是,它會將所有的列都當做二進位制來處理,沒有與型別掛鉤。因此,Hive0.11版本引入orcFile。OrcFile有以下幾點好處:
- 每個task只生成一個檔案,減輕hdfs壓力
- 儲存列型別,支援datetime, decimal和負責型別(struct, list, map, and union)
- 檔案中儲存輕量級索引
- 跳過不需的row group
- seek到指定的row
- 根據列型別進行壓縮
- 整數型別:run-length encoding
- string型別:dictionary encoding
- 不同的recordReader併發讀同一檔案
- split時,無需掃描標記
- 可以限制讀寫佔用的記憶體
- 使用pb存放元資料,支援新增和移除列
結構
orc dump工具
// Hive version 0.11 through 0.14:
hive --orcfiledump <location-of-orc-file>
// Hive version 0.15 and later:
hive --orcfiledump [-d] [--rowindex <col_ids>] <location-of-orc-file>
// Hive version 1.2.0 and later:
hive --orcfiledump [-d] [-t] [--rowindex <col_ids>] <location-of-orc-file>
// Hive version 1.3.0 and later:
hive --orcfiledump [-j] [-p] [-d] [-t] [--rowindex <col_ids>] [--recover] [--skip-dump]
[--backup-path <new-path>] <location-of-orc-file-or-directory>
配置
KEY | Default | Notes |
---|---|---|
orc.compress | ZLIB | 壓縮演算法,NONE/ZLIB/SNAPPY |
orc.compress.size | 262,144 | 每個壓縮塊大小,也是壓縮儲存stripe資料快取大小 |
orc.stripe.size | 67,108,864 | stripe大小 |
orc.row.index.stride | 10,000 | 索引資料間隔行(必須>=1000),即每10,000行資料,建一次索引,也是劃分rowGroup的依據 |
orc.create.index | true | 是否建行級索引 |
split讀取原理
涉及配置
- hive.optimize.index.filter
- 預設值:false
- 意義:
- 是否使用索引優化物理執行計劃
- 是否將條件下推到TableScanOperator中(讀取資料、做split時會使用此條件資訊)
- orcFile需要設定為true,才能獲取到過濾條件,進行stripe過濾
- hive.exec.orc.zerocopy
- 預設:false
- 讀取orc檔案時,是否使用0拷貝
- hive.input.format
- 預設:CombineHiveInputFormat
- 當使用combine方式時,會將小檔案進行合併,但是不會用到OrcInputFormat的過濾stripe機制
- 當使用
org.apache.hadoop.hive.ql.io.HiveInputFormat
,會呼叫OrcInputFormat的getSplits方法
,過濾不符合要求的stripe
- hive.optimize.index.filter
開啟條件及優缺點
這裡只討論非combine方式的split個讀取方式。- 觸發條件:
- set hive.input.format=org.apache.hadoop.hive.ql.io.HiveInputFormat;(必選)
- set hive.optimize.index.filter=true;(可選)
- 是否條件下推到TS,進行條件過濾,
建議開啟
- 是否條件下推到TS,進行條件過濾,
- set hive.exec.orc.zerocopy=true;(可選)
- 讀取orc檔案,是否使用0拷貝,
建議開啟
- 讀取orc檔案,是否使用0拷貝,
- 上述3個配置都開啟情況
- 優點:
- 做split時:
- 可以將不符合條件的stripe提前過濾,減少map個數
- 讀取時:
- 可以直接跳過不符合條件的rowGroup,無需讀取多餘的資料
- 做split時:
- 缺點:
- 不會combine,有可能會因為小檔案過多,導致map數過多
- 依賴使用者where條件,如果where條件過濾的資料不是很多,可能不會過濾stripe,導致map數過多(同時增加額外的計算,導致效能有所下降)
- 優點:
- 觸發條件:
原理介紹
- split
- 步驟1:stripe1,設定offset1和end1
- 步驟2:stripe2被過濾條件過濾,
stripe1則會產生一個split
- 步驟3:stripe3,設定offset2和end2
- 步驟4:stripe4和stripe3處於不同的block,
stripe3則會產生一個split
,offset和end分別指向stripe4的開始和結束位置 - 步驟5:stripe5,offset不變,end指向stripe5的結束位置
- 步驟6:stripe6,此時(end4-offset4)>maxSplitSize,
stripe4/5/6則會產生一個split
- 步驟7:stripe7,到達檔案結束,
stripe7產生一個split
- 讀取
- 讀取footer:獲取列資訊、索引位置資訊、資料位置資訊等
- 讀取indexData
- 根據
orc.row.index.stride
的值,劃分rowGroup,每個rowGroup的索引資料條數為orc.row.index.stride
的值 - 根據索引資料的資訊(max/min),判斷每個rowGroup是否滿足下推的where條件,實際讀取資料時進行skip
- 根據
- 讀取實際資料
- 讀取每列的資料,當遇到被過濾的rowGroup時,會skip掉,減少讀取的資料量
- split
優缺點
- 優點
- 可以提前過濾無需的stripe,減少split個數
- 讀取時,可以過濾不滿足條件的rowGroup,減少讀取數
- 缺點
- 做split時,stripe不會合並,有可能導致split數比combine方式更多
- 也有可能資料量少的split數比資料量多的split數多
- 優點
測試結果
stripeSize為128M
- sql1
select log_date,log_time,hh24,area_country,area_prov,area_city from tbl_orc_128M where dt='20161109' and hh24='19' and
channel_id=179569143limit 100;
- combine方式
- map數:1310
- 會進行列skip
Reading ORC rows from hdfs://bipcluster/bip/external_table/xx/tbl_orc_128M/dt=20161109/000856_0 with {include: [true, true, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, true, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false], offset: 0, length: 225585161}
- combine方式+條件下推
- map數:1310
- 會進行列skip
- 會進行rowGroup的skip
- 非combine方式
- map數:1747
- 會進行列skip
- 非combine方式+條件下推
- map數:43
- 會進行列skip
- 會進行rowGroup的skip:
- sql2
select log_date,log_time,hh24,area_country,area_prov,area_city from tbl_orc_128M where dt='20161109' and hh24='19' limit 100;
- combine方式
- map數:1310
- 會進行列skip
- combine方式+條件下推
- map數:1310
- 會進行列skip
- 會進行rowGroup的skip
- 非combine方式
- map數:1747
- 會進行列skip
- 非combine方式+條件下推
- map數:1747
- 會進行列skip
- 會進行rowGroup的skip:
- sql1
stripeSize為64M
- sql1
select log_date,log_time,hh24,area_country,area_prov,area_city from tbl_orc_64M where dt='20161109' and hh24='19' and
channel_id=179569143limit 100;
- combine方式
- map數:1448
- 會進行列skip
- combine方式+條件下推
- map數:1448
- 會進行列skip
- 會進行rowGroup的skip
- 非combine方式
- map數:3494
- 會進行列skip
- 非combine方式+條件下推
- map數:0
- sql2
select log_date,log_time,hh24,area_country,area_prov,area_city from tbl_orc_64M where dt='20161109' and hh24='19' limit 100;
- combine方式
- map數:1448
- 會進行列skip
- combine方式+條件下推
- map數:1448
- 會進行列skip
- 會進行rowGroup的skip
- 非combine方式
- map數:3494
- 會進行列skip
- 非combine方式+條件下推
- map數:3494
- 會進行列skip
- 會進行rowGroup的skip:
- sql1