Hive生产场景的十大经验总结

Hive生产场景的十大经验总结

1 Hive外部表转换

先转换为Hive内部表再进行删除,注意external的大小写形式。

  alter table table_name set tblproperties('EXTERNAL'='FALSE');
  drop  table_name;

2 Hive表数据删除

  • 删除分区
alter table test_table drop partition(year='2018');
  • 删除表(非必要,不用执行)
drop table if exists test_table ;
  • 删除hdfs上的数据
hadoop fs -rm -r /test/test_table/year=2021-01-01

注意Hive外部表需要转换为内部表,执行以上语句才真正删除;否则删除外部表仅删除元数据,真实数据依然存在。

3 数据同步策略

数据大小t是否有更新字段新增数据量tODS层同步策略是否删除DWD层同步策略
t>20G每日全量分区删除前天分区全删全插
t>20Gt<128M按月或年增量分区新老数据对比按分区插入
t>20Gt>=128M按日增量分区新老数据对比按分区插入
10G<t<20G每日全量分区删除前一天分区全删全插
10G<t<20Gt<128M按月或年增量分区新老数据对比按分区插入
T<5G每日全量分区删除前一天分区全删全插

4 Hive分区修复

MSCK REPAIR TABLE命令用来解决因 hdfs dfs -put或者hdfs api写入hive分区表时数据在hive中无法被查询到的问题。

Hive的metastore服务存储Hive元数据信息,例如数据库名,表名或者表的分区等。当进行Hive表的insert和update等更新操作时,相应的分区信息在metastore中更新,而前面提到的使用hdfs命令操作时,Hive的MetaStore元数据信息无法及时更新,导致数据查询异常。

如果插入分区数据量很多的话,你用ALTER TABLE table_name ADD PARTITION一个个分区添加十分麻烦。这时可以使用MSCK REPAIR TABLE。只需要运行MSCK REPAIR TABLE命令,hive就会去检测此表在hdfs上的文件信息,把没有写入metastore的所有分区信息写入metastore。

5 动态分区开启

set hive.exec.dynamic.partition=true; -- 已开启可以不执行
set hive.exec.dynamic.partition.mode=nonstrict;

6 小文件处理

6.1 小文件产生原因

hive 中的小文件常发生于 hive 表中导入数据后,先看下 hive 导入数据的几种方式。

1)insert into 表中插入数据

insert into table test_table values (1,'aa',11),(2,'bb',22);

这种方式每次插入时都会产生一个文件,如果不注意的话会产生大量的小文件堆积。虽然这种方式生产环境很少使用,也强烈禁止使用!!

2)通过load命令加载数据

load data local inpath '/export/score.csv' overwrite into table A  -- 导入文件

load data local inpath '/export/score' overwrite into table A   -- 导入文件夹

少数场景可以使用load命令导入文件或文件夹。当导入文件时,hive表生成相应的文件;当导入文件夹时,hive表文件数量为文件夹下所有文件总数。

3)通过查询加载数据

insert overwrite table test_table  
select s_id,c_name,s_score from B;

这种方式是生产环境中常用的,也是最容易产生小文件的方式之一。

根据Hive的底层执行原理,最终SQL会被转换为MapReduce执行task任务。Hive导入数据时会启动 MR 任务,MR中 reduce 有多少个就输出多少个文件。

  • 一般情况下Hive文件数 = ReduceTask数量 * 分区数
  • 存在一些简单任务没有reduce阶段只有map阶段,则Hive文件数=MapTask数量*分区数

因此每执行一次insert时hive中至少产生一个文件,因为 insert 语句执行底层至少会产生一个MapTask任务。甚至有的业务需要每几分钟就要把数据同步到 hive 中,这样产生的文件就会很多。

6.2 小文件过多产生的影响

1)对HDFS影响

HDFS本身不适合存储大量小文件,小文件过多会导致namenode内存使用过多,提供读写HDFS读写访问响应缓慢,严重影响HDFS的性能。

2) 对 Hive的影响

Hive查询机制会把每个小文件都会当成一个输入Block块,相应启动一个Map任务。而一个Map任务启动耗时远远大于逻辑处理的时间,造成很大的资源浪费。同时可执行的Map数量是受限的。

6.3 怎么解决小文件过多

1) 使用hive自带concatenate 命令

#非分区表
alter table test_table concatenate;

#分区表
alter table test_table partition(day=20201224) concatenate;

# 向 test_table 表中插入数据
> hive (test)> insert into table test_table values (1,'aa',11),(2,'bb',22);
> hive (test)> insert into test_table  values (3,'cc',33),(4,'dd',44);

# 执行以上语句,test_table 表下就会有2个小文件,在hive命令行执行如下语句

# 查看test_table 表下文件数量

> hive (test)> dfs -ls /user/hive/warehouse/test/test_table 
  -rwxr-xr-x   3 root supergroup        257 2021-10-24 14:46 
  /user/hive/warehouse/test/test_table/000000_0
  -rwxr-xr-x   3 root supergroup        257  2021-10-24 14:47 /user/hive/warehouse/test/test_table/000000_0_copy_1

# 可以看到有2个小文件,然后使用 concatenate 进行合并
> hive (test)> alter table test_table concatenate;

# 再次查看test_table表下文件数量, 已合并成一个文件
> hive (default)> dfs -ls /user/hive/warehouse/A;
  -rwxr-xr-x   3 root supergroup        514 2021-10-24 14:59 
  /user/hive/warehouse/test/test_table/000000_0

注意:
1)concatenate 命令目前仅支持 RCFILE 和 ORC 文件类型
2)concatenate合并小文件时不能指定合并后的文件数量(可多次执行)
3)多次使用concatenate后文件数量不在变化,可以修改参数 mapreduce.input.fileinputformat.split.minsize=256mb

2) 调整参数减少Map数量

  • 调整map输入合并小文件的参数
# 执行Map前进行小文件合并
  -- CombineHiveInputFormat底层是 Hadoop的 CombineFileInputFormat 方法
  -- 此方法是在mapper中将多文件合成一个split作为输入

  set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; -- 默认

# 设置Map最大输入大小(此值决定合并后文件的数量)
  set mapred.max.split.size=256000000;   -- 256M

#  设置每个节点split的大小(此值决定多个DataNode上的文件是否需要合并)
  set mapred.min.split.size.per.node=100000000;  -- 100M

#  设置rack机架节点split的大小(此值决定了多个交换机上的文件是否需要合并)
set mapred.min.split.size.per.rack=100000000;  -- 100M
  • 设置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;   -- 256M

# 当输出文件的平均大小小于该值时,启动一个独立的MapReduce任务进行文件merge
  set hive.merge.smallfiles.avgsize=18000000;   -- 18M 
  • 启用压缩
# hive的查询结果输出是否进行压缩
  set hive.exec.compress.output=true;

# MapReduce Job的结果输出是否使用压缩
  set mapreduce.output.fileoutputformat.compress=true;

3) 调整参数减少Reduce的数量

#reduce 的个数决定输出的文件的个数,可以调整reduce的个数控制hive小文件数量。

# 设置reduce的数量有两种方式,第一种是直接设置reduce个数
  set mapreduce.job.reduces=10;

# 第二种是设置每个reduce的大小,Hive会根据数据总大小推测reduce个数
  set hive.exec.reducers.bytes.per.reducer=2480000000; -- 默认是1G,设置为2G

# 使用distribute by 随机打散,将文件分桶存储
 set mapreduce.job.reduces=10;
 insert overwrite table A partition(dt)
 select * from B
 distribute by rand();

4) 使用hadoop的archive将小文件归档

Hadoop Archive简称HAR,是一个高效地将小文件放入HDFS块中的文件存档工具。能够将多个小文件打包成一个HAR文件,减少namenode内存使用。

# 用来控制归档是否可用
  set hive.archive.enabled=true;

# 设置父目录
  set hive.archive.har.parentdir.settable=true;

# 设置需要归档文件的大小
  set har.partfile.size=1099511627776;

#  命令归档
  ALTER TABLE A ARCHIVE PARTITION(dt='2020-12-24', hr='12');

# 恢复归档文件
  ALTER TABLE A UNARCHIVE PARTITION(dt='2020-12-24', hr='12');

7 Hive修改表路径

7.1 内部表

  • 1)设置新路径
 alter table test_table 
 set location 'hdfs://xxx/hive/warehouse/test.db/test_table
  • 2)移动文件地址
dfs -mv /hive/warehouse/test.db/test_table /hive/warehouse/test.db/test_table2

7.2 外部表

  • 1)删除旧表
  drop table table1;
  • 2)移动文件到新位置
 dfs -mv /hive/warehouse/test.db/tb_table1 /hive/warehouse/test.db/tb_table2
  • 3)新建新表, 并且指定路径为新地址
  create EXTERNAL table test_table (....) location '/hive/warehouse/test.db/test_table2'
  • 4)恢复元数据
  MSCK REPAIR TABLE table2;

8 Hive INSERT OVERWRITE 原理

Hive中使用INSERT OVERWRITE时,数据会先被写入到临时文件内,类似于 .hive-staging_hive_开头的文件;然后删除所有原文件,将临时文件重命名为原文件

9 Hive Group By数据倾斜优化

groupby引起的倾斜优化可设置下面参数。

set hive.map.aggr = true 
set hive.groupby.skewindata=true

底层原理: Hive的查询计划会生成两个 MapReduce Job,启用groupby的负载均衡。

  • MapReduce Job 1:Map 输出结果集随机分布到 每个Reduce 中,并在每个Reduce 部分聚合输出结果。导致相同的 Key 可能被分布到不同的 Reduce 中,从而达到负载均衡目的;
  • MapReduce2: 基于预处理结果,根据GroupBy的 Key 分布到 Reduce 中,这过程保证相同的GroupBy Key被分布到同一个Reduce中,最后完成最终的聚合操作。

10 Hive Decimal数据类型报NUll

这是一个容易被忽视的小细节: DECIMAL(9,8)代表最多9位数字,后8位是小数。此时小数点前最多有1位数字,如果超过一位则会变成null。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值