11.Hive壓縮,文件格式及優(yōu)化

1. 日志文件加載案例:

需求描述:在日志文件目錄中,按天建文件夾,并且在每個天文件夾中,每小時有一個日志文件。程序自動每天將這些文件load到hive表對應的天分區(qū)的小時分區(qū)內(nèi)。例如下面的目錄結構:


文件目錄結構.png

首先,需要根據(jù)實際文件的情況(查看分隔符)來確定我們建表的分隔符。實際上,在顯示時,TAB和空格十分相似,不好區(qū)分,可以使用UltraEdit工具的功能來查看。使用方法:“視圖 -> 顯示空格/制表符”。
下面是建表DDL:

CREATE TABLE `testdb.dw_web_log`(
  `id` string, 
  `url` string, 
  `referer` string, 
  `keyword` string, 
  `type` string, 
  `guid` string, 
  `pageid` string, 
  `moduleid` string, 
  `linkid` string, 
  `attachedinfo` string, 
  `sessionid` string, 
  `trackeru` string, 
  `trackertype` string, 
  `ip` string, 
  `trackersrc` string, 
  `cookie` string, 
  `ordercode` string, 
  `tracktime` string, 
  `enduserid` string, 
  `firstlink` string, 
  `sessionviewno` string, 
  `productid` string, 
  `curmerchantid` string, 
  `provinceid` string, 
  `cityid` string, 
  `fee` string, 
  `edmactivity` string, 
  `edmemail` string, 
  `edmjobid` string, 
  `ieversion` string, 
  `platform` string, 
  `internalkeyword` string, 
  `resultsum` string, 
  `currentpage` string, 
  `linkposition` string, 
  `buttonposition` string)
PARTITIONED BY ( 
  `date` string, 
  `hour` string)
ROW FORMAT DELIMITED 
  FIELDS TERMINATED BY '\t' 

下面使用兩種方式實現(xiàn), hive -e "sql" 和 hive --hiveconf -f 。

1. hive -e方式:

通過shell腳本,可以將變量拼接到sql語句中,并load數(shù)據(jù)到hive表中。下邊腳本供參考load_web_log.sh:

#!/bin/bash
#You must input one parameter;
if [ $# -ne 1 ]  ; then
echo "You must provide one parameter (date) unix timestamp !!"
exit 1
fi

date=`date -d @$1 +%Y%m%d`
logdir=/home/natty.ma/bigdata/hive/WebLog
HIVE_HOME=/spark/hive

log_num=`ls ${logdir}/${date}|wc -l`

if [ ${log_num} -lt 1 ]; then
  echo "There are no log files this day:"${date}
  exit 1 
else
  for i in `ls ${logdir}/${date}`; do
    # cut 2 characters from the 9th location  ;  get the hour of the file
    hour=${i:8:2}
    $HIVE_HOME/bin/hive -e "load data local inpath '${logdir}/${date}/${i}' overwrite into table testdb.dw_web_log partition(date='${date}',hour='${hour}')"
  done
fi

調(diào)用該腳本,需要傳入unix時間戳作為參數(shù):

$ ./load_web_log.sh `date -d "-1 days" +%s`

2. hive --hiveconf 方式傳參:

參考腳本load_web_log_1.sh :

#!/bin/bash
#You must input one parameter;
if [ $# -ne 1 ]  ; then
echo "You must provide one parameter (date) unix timestamp !!"
exit 1
fi

date=`date -d @$1 +%Y%m%d`
logdir=/home/natty.ma/bigdata/hive/WebLog
HIVE_HOME=/spark/hive/

log_num=`ls ${logdir}/${date}|wc -l`

if [ ${log_num} -lt 1 ]; then
  echo "There are no log files this day:"${date}
  exit 1 
else
  for i in `ls ${logdir}/${date}`; do
    # cut 2 characters from the 9th location  ;  get the hour of the file
    hour=${i:8:2}
    fileDir=${logdir}/${date}/${i}
    ${HIVE_HOME}/bin/hive --hiveconf fileDir=${fileDir} --hiveconf date=${date} --hiveconf hour=${hour} -f load_web_log.sql
  done
fi

這里使用了一個sql文件load_web_log.sql,該文件作用很簡單(只有一條load語句),執(zhí)行SQL,并讀取變量即可。讀取變量時,需要注意,在sql文件中,如果要讀取hiveconf傳過來的fileDir變量,需要使用${hiveconf:fileDir}

load data local inpath '${hiveconf:fileDir}' overwrite into table testdb.dw_web_log partition(date='${hiveconf:date}',hour='${hiveconf:hour}')

2. MapReduce和hive中的數(shù)據(jù)壓縮。

1.壓縮特點:

多數(shù)Hadoop作業(yè)在執(zhí)行時,都受限于I/O瓶頸。對數(shù)據(jù)做壓縮,可以大量減少磁盤的存儲空間,同時壓縮后的文件在磁盤間傳輸和I/O也會大大減少;當然壓縮和解壓縮也會帶來額外的CPU開銷,但是卻可以節(jié)省更多的I/O和使用更少的內(nèi)存開銷。Job的性能可能會通過開啟壓縮而提高,但是必須要考慮到 Splittability。

2.壓縮算法:

查看自己的hadoop版本支持的壓縮算法(庫):

$ bin/hadoop checknative

常見的壓縮算法包括:bzip2,gzip,lzo,lz4,snappy等。一般地,評判一個壓縮算法好壞,需要綜合考慮“壓縮比”和“解壓速度”兩個指標。一般情況下,壓縮比越大表明文件壓縮后占用空間越小,但同時,需要的解壓時間也越多。所以,需要綜合考慮。目前,lz4和snappy使用比較廣泛。
壓縮比: bzip2 > gzip > lzo

MapReduce中的壓縮.png

從上圖發(fā)現(xiàn),可以在3個過程使用壓縮:

  • Map階段前壓縮
  • Shuffle階段 { Compress Intermediate Data (Map Output) }
  • Reduce階段后 { Compress Reducer/Job Output (Reducer Output) }

一般情況下,可能會設置啟用 Shuffle階段壓縮 和 Reduce階段后 壓縮。
(1)Shuffle階段壓縮:
Map輸出需要寫到磁盤,并且需要占用I/O在集群內(nèi)傳輸。壓縮可以減少寫入磁盤I/O和網(wǎng)絡傳輸I/O,提高性能。可以使用Snappy、LZO等壓縮算法。
(2)Reduce階段壓縮:
MapReduce輸出用來歸檔或者chaining Mapreduce作業(yè)。Reduce階段使用壓縮可以節(jié)省磁盤空間。

在hadoop-common-xxx.jar中有定義壓縮算法的類,在包org.apache.hadoop.io.compress下。例如以下幾個類:
org.apache.hadoop.io.compress.SnappyCodec
org.apache.hadoop.io.compress.GzipCodec
org.apache.hadoop.io.compress.Lz4Codec

3.壓縮配置:

在MapReduce和Hive中指定壓縮的方式不一樣。
1.MapReduce指定壓縮:
(1)中間壓縮:

mapreduce.map.output.compress=true
mapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.DefaultCodec

(2)Reduce結果壓縮:

mapreduce.output.fileoutputformat.compress=true
mapreduce.output.fileoutputformat.compress.codec=org.apache.hadoop.io.compress.DefaultCodec

如果需要永久配置,需要修改mapred-site.xml。
2.Hive指定壓縮:
(1)中間壓縮:

set hive.exec.compress.intermediate=true
set mapred.map.output.compression.codec=org.apache.hadoop.io.compress.DefaultCodec
set mapred.map.output.compression.type=(BLOCK/RECORD) 

(2)Reduce結果壓縮:

set hive.exec.compress.output=true
set mapred.output.compression.codec=org.apache.hadoop.io.compress.DefaultCodec
set mapred.output.compression.type=(BLOCK/RECORD) 

如果需要永久生效,需要配置hive-site.xml。

反序列化用來讀取數(shù)據(jù),序列化用來寫入數(shù)據(jù):
HDFS files --> InputFileFormat --> <key, value> --> Deserializer --> Row object
Row object --> Serializer --> <key, value> --> OutputFileFormat --> HDFS files
反序列化將一個String,或者記錄的二級制表示轉(zhuǎn)化成一個Hive可以處理的java對象。DeSerializer通常用于讀數(shù)據(jù),例如SELECT語句。
序列化是將一個Hive處理的java對象轉(zhuǎn)化成Hive可以寫入HDFS的對象。Serializer通常用于寫數(shù)據(jù),例如INSERT ... SELECT ...語句。
Serde類中 的initialize() 只執(zhí)行一次,獲取表字段和字段類型信息。利用記錄的類型信息,為記錄(row)實例化ObjectInspector對象。ObjectInspector是Hive對象,用來檢查和描述復雜類型的層次結構。

http://blog.cloudera.com/blog/2012/12/how-to-use-a-serde-in-apache-hive/

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容