1. 程式人生 > >orcFile split和讀資料原理總結(hive0.13)

orcFile split和讀資料原理總結(hive0.13)

背景

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
  • 開啟條件及優缺點
    這裡只討論非combine方式的split個讀取方式。

    • 觸發條件:
      • set hive.input.format=org.apache.hadoop.hive.ql.io.HiveInputFormat;(必選)
      • set hive.optimize.index.filter=true;(可選)
        • 是否條件下推到TS,進行條件過濾,建議開啟
      • set hive.exec.orc.zerocopy=true;(可選)
        • 讀取orc檔案,是否使用0拷貝,建議開啟
    • 上述3個配置都開啟情況
      • 優點:
        • 做split時:
          • 可以將不符合條件的stripe提前過濾,減少map個數
        • 讀取時:
          • 可以直接跳過不符合條件的rowGroup,無需讀取多餘的資料
      • 缺點:
        • 不會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掉,減少讀取的資料量
  • 優缺點

    • 優點
      • 可以提前過濾無需的stripe,減少split個數
      • 讀取時,可以過濾不滿足條件的rowGroup,減少讀取數
    • 缺點
      • 做split時,stripe不會合並,有可能導致split數比combine方式更多
      • 也有可能資料量少的split數比資料量多的split數多

測試結果

  1. 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' andchannel_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:
  2. 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' andchannel_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:

參考文件