1. 日志文件加载案例:
需求描述:在日志文件目录中,按天建文件夹,并且在每个天文件夹中,每小时有一个日志文件。程序自动每天将这些文件load到hive表对应的天分区的小时分区内。例如下面的目录结构:
首先,需要根据实际文件的情况(查看分隔符)来确定我们建表的分隔符。实际上,在显示时,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
从上图发现,可以在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 --> <key, value> --> Deserializer --> Row object
Row object --> Serializer --> <key, value> --> 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/