11.Hive压缩,文件格式及优化

1. 日志文件加载案例:

需求描述:在日志文件目录中,按天建文件夹,并且在每个天文件夹中,每小时有一个日志文件。程序自动每天将这些文件load到hive表对应的天分区的小时分区内。例如下面的目录结构:


文件目录结构.png

首先,需要根据实际文件的情况(查看分隔符)来确定我们建表的分隔符。实际上,在显示时,TAB和空格十分相似,不好区分,可以使用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' 

下面使用两种方式实现, hive -e "sql" 和 hive --hiveconf -f 。

1. hive -e方式:

通过shell脚本,可以将变量拼接到sql语句中,并load数据到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

调用该脚本,需要传入unix时间戳作为参数:

$ ./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语句),执行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中的数据压缩。

1.压缩特点:

多数Hadoop作业在执行时,都受限于I/O瓶颈。对数据做压缩,可以大量减少磁盘的存储空间,同时压缩后的文件在磁盘间传输和I/O也会大大减少;当然压缩和解压缩也会带来额外的CPU开销,但是却可以节省更多的I/O和使用更少的内存开销。Job的性能可能会通过开启压缩而提高,但是必须要考虑到 Splittability。

2.压缩算法:

查看自己的hadoop版本支持的压缩算法(库):

$ bin/hadoop checknative

常见的压缩算法包括:bzip2,gzip,lzo,lz4,snappy等。一般地,评判一个压缩算法好坏,需要综合考虑“压缩比”和“解压速度”两个指标。一般情况下,压缩比越大表明文件压缩后占用空间越小,但同时,需要的解压时间也越多。所以,需要综合考虑。目前,lz4和snappy使用比较广泛。
压缩比: bzip2 > gzip > lzo

11.Hive压缩,文件格式及优化_第1张图片
MapReduce中的压缩.png

从上图发现,可以在3个过程使用压缩:

  • Map阶段前压缩
  • Shuffle阶段 { Compress Intermediate Data (Map Output) }
  • Reduce阶段后 { Compress Reducer/Job Output (Reducer Output) }

一般情况下,可能会设置启用 Shuffle阶段压缩 和 Reduce阶段后 压缩。
(1)Shuffle阶段压缩:
Map输出需要写到磁盘,并且需要占用I/O在集群内传输。压缩可以减少写入磁盘I/O和网络传输I/O,提高性能。可以使用Snappy、LZO等压缩算法。
(2)Reduce阶段压缩:
MapReduce输出用来归档或者chaining Mapreduce作业。Reduce阶段使用压缩可以节省磁盘空间。

在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。

反序列化用来读取数据,序列化用来写入数据:
HDFS files --> InputFileFormat --> --> Deserializer --> Row object
Row object --> Serializer --> --> OutputFileFormat --> HDFS files
反序列化将一个String,或者记录的二级制表示转化成一个Hive可以处理的java对象。DeSerializer通常用于读数据,例如SELECT语句。
序列化是将一个Hive处理的java对象转化成Hive可以写入HDFS的对象。Serializer通常用于写数据,例如INSERT ... SELECT ...语句。
Serde类中 的initialize() 只执行一次,获取表字段和字段类型信息。利用记录的类型信息,为记录(row)实例化ObjectInspector对象。ObjectInspector是Hive对象,用来检查和描述复杂类型的层次结构。

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

你可能感兴趣的:(11.Hive压缩,文件格式及优化)