hive 表操作

hive 数据分析

Posted by 果然 on April 13, 2022

本文主要讲述数据写入hive表。主要有三种方法:

  • Insert…Values
  • Insert…Select
  • Load

前期准备:已有gmall.dwd_ad_log表,且该表为分区表,dt日期为分区。
鉴于此,我们在创建表时,需要再额外添加一个字段。

show create table dwd_ad_log
show partitions dwd_ad_log

建库与建表

create table `test`
`mid_id` string, 
`user_id` string, 
`version_code` string, 
`version_name` string, 
`lang` string, 
`source` string, 
`os` string, 
`area` string, 
`model` string, 
`brand` string, 
`sdk_version` string, 
`gmail` string, 
`height_width` string, 
`app_time` string, 
`network` string, 
`lng` string, 
`lat` string, 
`entry` string, 
`action` string, 
`content` string, 
`detail` string, 
`ad_source` string, 
`behavior` string, 
`newstype` string, 
`show_style` string, 
`server_time` string,
`id` string)  
row format delimited fields terminated by ','
stored as textfile;

使用 insert into…select写入数据

insert into test select * from dwd_ad_log

对于 select 一些聚合操作等,just shift it out in a subquery:

select a from(
select a, avg(b) as avgb from asm group by a) as t
order by avgb;

该方法在生产环境中较常用,也是最容易产生小文件的情况。

使用 insert into…values写入数据

insert into table test values(),(),();

使用 load 写入数据

load data local inpath 'hdfs://192.168.184.131:9000/warehouse/gmall/dwd/dwd_ad_log/xxx.txt' into table test;

注意:若txt中包含有中文,需要确保文件格式为utf-8,否则乱码。
注:若发现使用load语句写入数据比insert语句快很多倍,这是因为hive并不对scheme进行校验,仅仅是将数据文件挪到hdfs系统上,也没有执行MR作业,因此从导入数据的角度而言,使用load要优于使用insert into…values。

表中数据写入指定路径

// 数据以csv格式写至本地路径
insert into/overwrite local directory '/test' row format delimited fields terminated by ',' select * from dwd_ad_log;  
// 数据以csv格式写入hdfs  
insert into/overwrite directory '/test' row format delimited fields terminated by ',' select * from dwd_ad_log;   

合并小文件

小文件过多产生的影响

-1. 对底层HDFS而言,HDFS本省不适合存储大量小文件,小文件过多会导致namenode元数据特别大,占用太多内存,严重影响hdfs的性能。
-2. 对hive而言,在进行查询时,每个小文件都会当成一个块,启动一个Map任务来完成,而一个map任务启动和初始化的时间远远大于逻辑处理时间,就会造成很大的资源浪费,而且,同时可执行的map数量是受限的。

concatenate

建表时,默认的文件类型为TextFile。
hive 提供了一个 alter table xxx CONCATENATE语句,用于合并小文件,但仅支持RCFILE和ORC文件类型。

create table xxx() stored as RCFile;  
alter table xxx concatenate;    // 可多次使用

当多次使用concatenate后文件数量不再变化,这个与参数mapreduce.input.fileinputformat.split.minsize=256mb 的设置有关,可设定每个文件的最小size。

partition 分区

表具有分区partition。

create table xxx() partitioned by `dt` row format delimited fields terminated by ','   
// 将dt相同的数据放在同一个reduce处理   
insert overwrite table xxx partition(dt) select * from aaa distribute by dt;
// 均匀分配 该SQL生产的文件数量为reduce个数 * 分区个数  
set hive.exec.reducers.bytes.per.reducer=5120000000;
insert overwrite table xxx partition(dt) select * from aaa distribute by rand();

调整参数减少map数量

设置map输入合并小文件的相关参数

set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;  
// 每个map最大输入大小 决定了合并后文件的数量
set mapred.max.split.size=256000000
// 一个节点上split的大小(至少) 决定了多个DataNode上的文件是否需要合并
set mapred.min.split.size.per.node=100000000
// 一个交换机下split的最小大小  决定了多个交互及上的文件是否需要合并
set maored.min.split.size.per.rack=100000000

设置map输出和reduce输出进行合并的相关参数

// 设置map端输出进行合并 默认为true
set hive.merge.mapfiles=true
// 设置reduce端输出进行合并  默认为false
set hive.merge.mapredfiles=true
// 设置合并文件的大小
set hive.merge.size.per.task=256*1000*1000
// 当输出文件的平均大小小于该值时,启动一个独立的MapReduce任务进行文件merge
set hive.merge.smallfiles.avgsize=160000000

启用压缩

// hive查询结果输出是否进行压缩
set hive.exec.compress.output=true
// MapReduce job的结果输出是否使用压缩
set mapreduce.output.fileoutputformat.compress=true

减少reduce的数量

reduce 的个数决定了输出文件个数,所以可以调节reduce的个数控制hive表的文件数量,hive中的分区函数 distribute by 正好控制MR中partition分区的,然后通过设置reduce的数量,结合分区函数让数据均衡的进入每个reduce即可。

set mapreduce.job.reduces = 10
set hive.exec.reducers.bytes.per.reducer=5120000000
set mapreduce.job.reduces=10
insert overwrite table a partition(dt) select * from B distribute by rand()

使用hadoop的archive将小文件归档

hadoop archive简称 HAR,是一个高效地将小文件放入HDFS块中的文件存档工具,它能够将多个小文件打包成一个HAR文件,这样在减少namenode内存使用的同时,仍然允许对文件进行透明的访问。

set hive.archive.enabled=true
set hive.archive.har.parentdir.settable=true

//  使用以下命令进行归档
alter table A archive partition(dt='2020-12-24',hr='12')
//  对已归档的分区恢复为原文件
alter table A unarchive partition(dt='2020-12-24',hr='12')

hive的map数和reduce数如何确定

RCFile和ORCFile

存储结构上

RCFile文件格式是FaceBook开源的一种Hive的文件存储格式,首先将表分为几个行组,对每个行组内的数据进行按列存储,每一列的数据都是分开存储,正是先水平划分,再垂直划分的理念。 在一般的行存储中,会将不同的列分开存储,这样在查询时会跳过某些列,但有时候存在一个表的有些列不再一个hdfs块上,所以在查询时,hive重组列的过程会浪费很多IO开销。而RCFile由于相同的列都是在一个HDFS块上,因此相对列存储而言会省很多资源。

存储空间上

RCFile采用游程编码,相同的数据不会重复存储,很大程度上节约了存储空间,尤其是字段中包含大量重复数据的时候。

懒加载

数据存储到表中都是压缩的数据,hive读取数据时会对其进行解压缩,但会针对特定的查询跳过不需要的列,这样也就省去了无用的列解压。

参考资料

  1. Sorting by average, then inserting into new table using Hive
  2. Hive 写入数据到Hive表(命令行)
  3. Hive:解决Hive创建文件数过多的问题