总结了一下在以往工作中,对于Hive SQL调优的一些理论利用,是日常积攒的一些优化技巧,如有出入,欢送在评论区留言探讨~

EXPLAIN 查看执行打算

建表优化

分区

  1. 分区表基本操作,partitioned
  2. 二级分区
  3. 动静分区

分桶

  1. 分桶表基本操作,clustered
  2. 分桶表次要是抽样查问,找出具备代表性的后果

抉择适合的文件格式和压缩格局

  1. LZO,拉兹罗
  2. Snappy
  3. 压缩速度快,压缩比高

HiveSQL语法优化

单表查问优化

  1. 列裁剪和分区裁剪,全表和全列扫描效率都很差,生产环境相对不要应用SELECT *,所谓列裁剪就是在查问时只读取须要的列,分区裁剪就是只读取须要的分区

    • 与列裁剪优化相干的配置项是hive.optimize.cp,默认是true
    • 与分区裁剪优化相干的则是hive.optimize.pruner,默认是true
    • HiveSQL解析阶段对应的则是ColumnPruner逻辑优化器
  2. Group By 配置调整,map阶段会把同一个key发给一个reduce,当一个key过大时就歪斜了,能够开启map端预聚合,能够无效缩小shuffle数据量并

    # 是否在map端聚合,默认为trueset hive.map.aggr = true;# 在map端聚合的条数set hive.groupby.mapaggr.checkintervel = 100000;# 在数据歪斜的时候进行平衡负载(默认是false),开启后会有 两个`mr工作`。# 当选项设定为true时,第一个 `mr工作` 会将map输入的后果随机调配到`reduce`,# 每个`reduce`会随机散布到`reduce`上,这样的处理结果是会使雷同的`group by key`分到不同的`reduce`上。# 第二个 `mr工作` 再依据预处理的后果按`group by key`分到`reduce`上,# 保障雷同`group by key`的数据分到同一个`reduce`上。# *切记!!!* # 这样能解决数据歪斜,然而不能让运行速度更快  # 在数据量小的时候,开始数据歪斜负载平衡可能反而会导致工夫变长  # 配置项毕竟是死的,单纯靠它有时不能基本上解决问题# 因而还是倡议自行理解数据歪斜的细节,并优化查问语句  set hive.groupby.skewindata = true;
  3. Vectorization,矢量计算技术,通过设置批处理的增量大小为1024行单次来达到比单行单次更好的效率

    # 开启矢量计算  set hive.vectorized.execution.enabled = true;# 在reduce阶段开始矢量计算  set hive.vectorized.execution.reduce.enabled = true;
  4. 多重模式,一次读取屡次插入,同一张表的插入操作优化成先from tableinsert
  5. in/exists或者join用left semi join代替(为什么代替扩大一下~)

多表查问优化

  1. CBO优化,老本优化器,代价最小的执行打算就是最好的执行打算

    • join的时候表的程序关系,后面的表都会被加载到内存中,前面的表进行磁盘扫描
    • 通过hive.cbo.enable,主动优化hivesql中多个join的执行程序
    • 能够通过查问一下参数,这些个别都是true,无需批改

      set hive.cbo.enable = true;set hive.compute.query.using.stats = true;set hive.stats.fetch.column.stats = true;set hive.stats.fetch.partition.stats = true;
  2. 谓词下推(十分要害的一个优化),将sql语句中的where谓词逻辑都尽可能提前执行,缩小上游解决的数据量,
    在关系型数据库如MySQL中,也有谓词下推(Predicate Pushdown,PPD)的概念,
    它就是将sql语句中的where谓词逻辑都尽可能提前执行,缩小上游解决的数据量

    # 这个设置是默认开启的 # 如果敞开了然而cbo开启,那么敞开仍然不会失效 # 因为cbo会主动应用更为高级的优化打算  # 与它对应的逻辑优化器是PredicatePushDown# 该优化器就是将OperatorTree中的FilterOperator向上提set hive.optimize.pdd = true;# 举个例子# 对forum_topic做过滤的where语句写在子查问外部,而不是内部select a.uid,a.event_type,b.topic_id,b.titlefrom calendar_record_log aleft outer join (  select uid,topic_id,title from forum_topic  where pt_date = 20220108 and length(content) >= 100) b on a.uid = b.uidwhere a.pt_date = 20220108 and status = 0;
  3. Map Join,map join是指将join操作两方中比拟小的表间接散发到各个map过程的内存中,在map中进行join的操作。
    map join特地适宜大小表join的状况,Hive会将build tableprobe tablemap端间接实现join过程,毁灭了reduce,缩小shuffle,所以会缩小开销

    • set hive.auto.convert.join = true,配置开启,默认是true
    • 留神!!! 如果执行小表join大表,小表作为主连贯的主表,所有数据都要写出去,此时会走reduce阶段,mapjoin会生效
    • 大表join小表不受影响,上一条的起因次要是因为小表join大表的时候,map阶段不晓得reduce的后果其余reduce是否有,
    • 所以必须在最初reduce聚合的时候再解决,就产生了reduce的开销

      # 举个例子# 在最常见的`hash join`办法中,个别总有一张绝对小的表和一张绝对大的表,# 小表叫`build table`,大表叫`probe table`  # Hive在解析带join的SQL语句时,会默认将最初一个表作为`probe table`,# 将后面的表作为`build table`并试图将它们读进内存  # 如果表程序写反,`probe table`在后面,引发`OOM(内存不足)`的危险就高了  # 在维度建模数据仓库中,事实表就是`probe table`,维度表就是`build table`  # 假如当初要将日历记录事实表和记录项编码维度表来`join`  select a.event_type,a.event_code,a.event_desc,b.upload_timefrom calendar_event_code ainner join (select event_type,upload_time from calendar_record_logwhere pt_date = 20220108) b on a.event_type = b.event_type;
  4. Map Join,大表和大表的MapReduce工作,能够应用SMB Join

    • 间接join耗时会很长,然而依据某字段分桶后,两个大表每一个桶就是一个小文件,两个表的每个小文件的分桶字段都应该可能一一对应(hash值取模的后果)
    • 总结就是分而治之,留神两个大表的分桶字段和数量都应该保持一致

      set hive.optimize.bucketmapjoin = true;set hive.optimeize.bucketmapjoin.sortedmerge = true;hive.input.format = org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;
  5. 多表join时key雷同,这种状况会将多个join合并为一个mr 工作来解决

    # 举个例子# 如果上面两个join的条件不雷同  # 比方改成a.event_code = c.event_code  # 就会拆成两个MR job计算select a.event_type,a.event_code,a.event_desc,b.upload_timefrom calendar_event_code ainner join (  select event_type,upload_time from calendar_record_log  where pt_date = 20220108) b on a.event_type = b.event_typeinner join (  select event_type,upload_time from calendar_record_log_2  where pt_date = 20220108) c on a.event_type = c.event_type;
  6. 笛卡尔积,在生产环境中严禁应用

其余查问优化

  1. Sort By 代替 Order By,HiveQL中的order by与其余sql方言中的性能一样,就是将后果按某字段全局排序,这会导致所有map端数据都进入一个reducer中,
    在数据量大时可能会长工夫计算不完。如果应用sort by,那么还是会视状况启动多个reducer进行排序,并且保障每个reducer内部分有序。
    为了管制map端数据调配到reducerkey,往往还要配合distribute by一起应用,如果不加distribute by的话,map端数据就会随机调配到reducer

    # 举个例子select uid,upload_time,event_type,record_datafrom calendar_record_logwhere pt_date >= 20220108 and pt_date <= 20220131distribute by uidsort by upload_time desc,event_type desc;
  2. Group By代替Distinct,当要统计某一列的去重数时,如果数据量很大,count(distinct)就会十分慢,起因与order by相似,
    count(distinct)逻辑只会有很少的reducer来解决。然而这样写会启动两个mr工作(单纯distinct只会启动一个),
    所以要确保数据量大到启动mr工作overhead远小于计算耗时,才思考这种办法,当数据集很小或者key的歪斜比拟显著时,group by还可能会比distinct

数据歪斜

留神要和数据适量的状况辨别开,数据歪斜是大部分工作都曾经执行结束,然而某一个工作或者少数几个工作,始终未能实现,甚至执行失败,
而数据适量,是大部分工作都执行的很慢,这种状况须要通过裁减执行资源的形式来加快速度,大数据编程不怕数据量大,就怕数据歪斜,一旦数据歪斜,重大影响效率

单表携带了 Group By 字段的查问

  1. 工作中存在group by操作,同时聚合函数为countsum,单个key导致的数据歪斜能够这样通过设置开启map端预聚合参数的形式来解决

    # 是否在map端聚合,默认为trueset hive.map.aggr = true;# 在map端聚合的条数set hive.groupby.mapaggr.checkintervel = 100000;# 有数据歪斜的时候开启负载平衡,这样会生成两个mr工作set hive.groupby.skewindata = true;
  2. 工作中存在group by操作,同时聚合函数为countsum,多个key导致的数据歪斜能够通过减少reduce的数量来解决

    • 减少分区能够缩小不同分区之间的数据量差距,而且减少的分区时候不能是之前分区数量的倍数,不然会导致取模后果雷同持续分在雷同分区
    • 第一种批改形式

      # 每个reduce解决的数量set hive.exec.reduce.bytes.per.reducer = 256000000;# 每个工作最大的reduce数量set hive.exec.reducers.max = 1009;# 计算reducer数的公式,依据工作的须要调整每个工作最大的reduce数量  N = min(设置的最大数,总数量数/每个reduce解决的数量)
    • 第二种批改形式

      # 在hadoop的mapred-default.xml文件中批改set mapreduce.job.reduces = 15;

两表或多表的 join 关联时,其中一个表较小,然而 key 集中

  1. 设置参数减少map数量

    # join的key对应记录条数超过该数量,会进行分拆  set hive.skewjoin.key = 1000;# 并设置该参数为true,默认是falseset hive.optimize.skewjoin = true;# 下面的参数如果开启了会将计算数量超过阈值的key写进临时文件,再启动另外一个工作做map join  # 能够通过设置这个参数,管制第二个工作的mapper数量,默认10000set hive.skewjoin.mapjoin.map.tasks = 10000;
  2. 应用mapjoin,缩小reduce从根本上解决数据歪斜,参考HiveSQL语法优化 -> 多表查问优化 -> Map Join,大表和大表的MapReduce工作,SMB Join

两表或多表的 join 关联时,有 Null值 或 无意义值

这种状况很常见,比方当事实表是日志类数据时,往往会有一些项没有记录到,咱们视状况会将它置为null,或者空字符串-1等,
如果缺失的项很多,在做join时这些空值就会十分集中,连累进度,因而,若不须要空值数据,就提前写where语句过滤掉,
须要保留的话,将空值key用随机形式打散,例如将用户ID为null的记录随机改为负值

select a.uid,a.event_type,b.nickname,b.agefrom (  select   (case when uid is null then cast(rand()*-10240 as int) else uid end) as uid,  event_type from calendar_record_log  where pt_date >= 20220108) a left outer join (  select uid,nickname,age from user_info where status = 4) b on a.uid = b.uid;

两表或多表的 join 关联时,数据类型不对立

比方int类型和string类型进行关联,关联时候以小类型作为分区,这里intstring会到一个reduceTask中,如果数据量多,会造成数据歪斜

# 能够通过转换为同一的类型来解决cast(user.id as string)

独自解决歪斜key

这其实是下面解决空值办法的拓展,不过歪斜的key变成了有意义的,一般来讲歪斜的key都很少,咱们能够将它们抽样进去,
对应的行独自存入长期表中,而后打上一个较小的随机数前缀(比方0~9),最初再进行聚合

Hive Job 优化

Hive Map 优化

Map数量多少的影响

  1. Map数过大

    • map阶段输入文件太小,产生大量小文件
    • 初始化和创立map的开销很大
  2. Map数太小

    • 文件解决或查问并发度小,Job执行工夫过长
    • 大量作业时,容易梗塞集群

管制Map数的准则

依据理论状况,管制map数量须要遵循两个准则

  1. 第一是使大数据量利用适合的map
  2. 第二是使单个map工作解决适合的数据量

简单文件适当减少Map数

  1. input的文件都很大,工作逻辑简单,map执行十分慢的时候,能够思考减少map数,来使得每个map解决的数据量缩小,从而进步工作的执行效率
  2. 那么如何减少map的数量呢?在map阶段,文件先被切分成split块,而后每一个split切片对应一个Mapper工作
    FileInputFormat这个类先对输出文件进行逻辑上的划分,以128m为单位,将原始数据从逻辑上宰割成若干个split,每个split切片对应一个mapper工作
    所以说缩小切片的大小就可减少map数量
  3. 能够根据公式计算computeSliteSize(Math.max(minSize, Math.min(maxSize, blockSize))) = blockSize = 128m
  4. 执行语句:set mapreduce.input.fileinputformat.split.maxsize = 100;

小文件进行合并缩小Map数

为什么要进行小文件合并?因为如果一个工作有很多小文件(远远小于块大小128m),则每个小文件也会被当做一个块,用一个map工作来实现,
而一个map工作启动和初始化的工夫远远大于逻辑解决的工夫,就会造成很大的资源节约,同时可执行的map数是受限的
两种形式合并小文件

  1. Map执行前合并小文件,缩小map数量

    // 每个Map最大输出大小(这个值决定了合并后文件的数量)set mapred.max.split.size = 256000000;// 一个节点上split的至多的大小(这个值决定了多个DataNode上的文件是否须要合并)set mapred.min.split.size.per.node = 100000000;// 一个交换机下split的至多的大小(这个值决定了多个交换机上的文件是否须要合并)set mapred.min.split.size.per.rack = 100000000;// 执行Map前进行小文件合并set hive.input.format = org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
  2. Map-Reduce工作执行完结时合并小文件,缩小小文件输入

    // 设置map端输入进行合并,默认为trueset hive.merge.mapfiles = true;// 设置reduce端输入进行合并,默认为falseset hive.merge.mapredfiles = true;// 设置合并文件的大小,默认是256set hive.merge.size.per.task = 256 * 1000 * 1000;// 当输入文件的均匀大小小于该值时,启动一个独立的`MapReduce工作`进行文件`merge`。set hive.merge.smallfiles.avgsize = 16000000;

Map端预聚合缩小Map数量

  1. 相当于在map端执行combiner,执行命令:set hive.map.aggr = true;
  2. combiners是对map端的数据进行适当的聚合,其益处是缩小了从map端到reduce端的数据传输量
  3. 其作用的实质,是将map计算的后果进行二次聚合,使Key-Value<List>List的数据质变小,从而达到缩小数据量的目标

揣测执行

  1. 在分布式集群环境下,因为程序Bug(包含Hadoop自身的bug),负载不平衡或者资源散布不均等起因,会造成同一个作业的多个工作之间运行速度不统一,
    有些工作的运行速度可能显著慢于其余工作(比方一个作业的某个工作进度只有50%,而其余所有工作曾经运行结束),则这些工作会拖慢作业的整体执行进度
  2. Hadoop采纳了揣测执行(Speculative Execution)机制,它依据肯定的法令揣测出拖后腿的工作,并为这样的工作启动一个备份工作,
    让该工作与原始工作同时解决同一份数据,并最终选用最先胜利运行实现工作的计算结果作为最终后果
  3. 执行命令:set mapred.reduce.tasks.speculative.execution = true; # 默认是true
  4. 当然,如果用户对于运行时的偏差十分敏感的话,那么能够将这些性能敞开掉,如果用户因为输出数据量很大而须要执行长时间的map task或者reduce task的话,
    那么启动揣测执行造成的节约是十分微小的

正当管制Map数量的理论案例

假如一个SQL工作:

SELECT COUNT(1) FROM fx67ll_alarm_count_copyWHERE alarm_date = "2021-01-08";

该工作的输出目录inputdir是:/group/fx67ll_data/fx67ll_data_etl/date/fx67ll_alarm_count_copy/alarm_date=2021-01-08,共有194个文件,
其中很多是远远小于128m的小文件,总大小约9G,失常执行会用194个Map工作map总共耗费的计算资源:SLOTS_MILLIS_MAPS= 610,023
通过在Map执行前合并小文件,缩小Map数

# 后面三个参数确定合并文件块的大小# 大于文件块大小128m的,依照128m来分隔 # 小于128m,大于100m的,依照100m来分隔# 把那些小于100m的(包含小文件和分隔大文件剩下的),进行合并,最终生成了74个块set mapred.max.split.size=100000000;set mapred.min.split.size.per.node=100000000;set mapred.min.split.size.per.rack=100000000;set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

合并后,用了74个map工作,map耗费的计算资源:SLOTS_MILLIS_MAPS= 323,098,对于这个简略SQL工作,执行工夫上可能差不多,但节俭了一半的计算资源

再假如这样一个SQL工作:

SELECT data_fx67ll,COUNT(1),COUNT(DISTINCT id),SUM(CASE WHEN …),SUM(CASE WHEN …),SUM(…)FROM fx67ll_device_info_zsGROUP data_fx67ll

如果表fx67ll_device_info_zs只有一个文件,大小为120m,但蕴含几千万的记录,如果用1个map去实现这个工作,必定是比拟耗时的,
这种状况下,咱们要思考将这一个文件正当的拆分成多个
减少Reduce数量,来减少Map数量

set mapred.reduce.tasks=10;CREATE TABLE fx67ll_device_info_zs_tempASSELECT * FROM fx67ll_device_info_zsDISTRIBUTE BY RAND(123);

这样会将fx67ll_device_info_zs表的记录,随机的扩散到蕴含10个文件的fx67ll_device_info_zs_temp表中,
再用fx67ll_device_info_zs_temp代替下面sql中的fx67ll_device_info_zs表,
则会用10个map工作去实现,每个map工作解决大于12m(几百万记录)的数据,效率必定会好很多

Hive Reduce 优化

Reduce数量多少的影响

  1. map一样,启动和初始化reduce也会耗费工夫和资源
  2. 另外,有多少个reduce,就会有多少个输入文件,如果生成了很多个小文件,那么如果这些小文件作为下一个工作的输出,则也会呈现小文件过多的问题

管制Reduce数的准则

map一样,管制reduce数量须要遵循两个准则

  1. 第一是使大数据量利用适合的reduce
  2. 第二是使单个reduce工作解决适合的数据量

Hive本人如何确定Reduce数

reduce个数的设定极大影响工作执行效率,不指定reduce个数的状况下,Hive会猜想确定一个reduce个数,基于以下两个设定:

# 每个reduce工作解决的数据量,默认为 1000^3=1Ghive.exec.reducers.bytes.per.reducer# 每个工作最大的reduce数,默认为999hive.exec.reducers.max

计算reducer数的公式很简略N = min(参数2,总输出数据量 / 参数1)
即,如果reduce的输出(map的输入)总大小不超过1G,那么只会有一个reduce工作

举个例子:

SELECT alarm_date,        COUNT(1) FROM fx67ll_alarm_count_copyWHERE alarm_date = "2021-01-08"GROUP BY alarm_date;

该工作的输出目录inputdir是:/group/fx67ll_data/fx67ll_data_etl/date/fx67ll_alarm_count_copy/alarm_date=2021-01-08
总大小为9G多,因而这句有10个reduce

如何调整Reduce数量

留神!!!理论开发中,reduce的个数个别通过程序主动推定,而不人为干预,因为人为管制的话,如果使用不当很容易造成后果不精确,且升高执行效率

  1. 通过调整每个reduce工作解决的数据量来调整reduce个数,解决的数据量少了,工作数就多了

    # 设置每个reduce工作解决的数据量500M,默认是1Gset hive.exec.reducers.bytes.per.reducer = 500000000;SELECT alarm_date,        COUNT(1) FROM fx67ll_alarm_count_copyWHERE alarm_date = "2021-01-08"GROUP BY alarm_date;这次有20个reduce
  2. 间接调整每个Job中的最大reduce数量,过于简略粗犷,慎用,尽量不要,尽管设置了reduce的个数看起来如同执行速度变快了,然而理论并不是这样的

    # 设置每个工作最大的reduce数为15个,默认为999set mapred.reduce.tasks = 15;SELECT alarm_date,        COUNT(1) FROM fx67ll_alarm_count_copyWHERE alarm_date = "2021-01-08"GROUP BY alarm_date;这次有15个reduce

揣测执行

参考map优化的最初一项

什么状况下只有一个Reduce

很多时候你会发现工作中不论数据量多大,不论你有没有设置调整reduce个数的参数,工作中始终都只有一个reduce工作,
其实只有一个reduce工作的状况,除了数据量小于hive.exec.reducers.bytes.per.reducer参数值的状况外,还有以下起因:

  1. 没有Group By的汇总,例如:

    SELECT alarm_date,        COUNT(1) FROM fx67ll_alarm_count_copyWHERE alarm_date = "2021-01-08"GROUP BY alarm_date;写成SELECT COUNT(1) FROM fx67ll_alarm_count_copyWHERE alarm_date = "2021-01-08";留神防止这样状况的产生
  2. 用了Order by排序,因为它会对数据进行全局排序,所以数据量特地大的时候效率非常低,尽量避免
  3. 有笛卡尔积,生产环境必须严格防止

Hive 工作整体优化

Fetch抓取

Fetch抓取是指Hive在某些状况的查问能够不用应用mr 工作,例如在执行一个简略的select * from XX时,咱们只须要简略的进行抓取对应目录下的数据即可。
hive-default.xml.template中,hive.fetch.task.conversion(默认是morn),老版本中默认是minimal
该属性为morn时,在全局查找,字段查找,limit查找等都不走mr 工作

本地模式

Hive也能够不将工作提交到集群进行运算,而是间接在一台节点上解决,因为打消了提交到集群的overhead,所以比拟适宜数据量很小,且逻辑不简单的工作。
设置hive.exec.mode.local.auto为true能够开启本地模式,但工作的输出数据总量必须小于hive.exec.mode.local.auto.inputbytes.max(默认值128MB)
且mapper数必须小于hive.exec.mode.local.auto.tasks.max(默认值4)reducer数必须为0或1,才会真正用本地模式执行

并行执行

Hive中相互没有依赖关系的job间是能够并行执行的,最典型的就是多个子查问union all
在集群资源绝对短缺的状况下,能够开启并行执行,行将参数hive.exec.parallel设为true,
另外hive.exec.parallel.thread.number能够设定并行执行的线程数,默认为8,个别都够用。
留神!!!没资源无奈并行,且数据量小时开启可能还没不开启快,所以倡议数据量大时开启

严格模式

要开启严格模式,须要将参数hive.mapred.mode设为strict
所谓严格模式,就是强制不容许用户执行3种有危险的sql语句,一旦执行会间接失败,这3种语句是:

  1. 查问分区表时不限定分区列的语句
  2. 两表join产生了笛卡尔积的语句
  3. 用order by来排序但没有指定limit的语句

JVM重用

  1. 次要用于解决小文件过多的时候
  2. mr 工作中,默认是每执行一个task就启动一个JVM,如果task十分小而碎,那么JVM启动和敞开的耗时就会很长
  3. 能够通过调节参数mapred.job.reuse.jvm.num.tasks来重用
  4. 例如将这个参数设成5,那么就代表同一个mr 工作中程序执行的5个task能够重复使用一个JVM,缩小启动和敞开的开销,但它对不同mr 工作中的task有效

启用压缩

压缩job的两头后果数据和输入数据,能够用大量CPU工夫节俭很多空间,压缩形式个别抉择Snappy,效率最高。
要启用两头压缩,须要设定hive.exec.compress.intermediate为true,
同时指定压缩形式hive.intermediate.compression.codecorg.apache.hadoop.io.compress.SnappyCodec
另外,参数hive.intermediate.compression.type能够抉择对块(BLOCK)还是记录(RECORD)压缩,BLOCK的压缩率比拟高。
输入压缩的配置基本相同,关上hive.exec.compress.output即可

采纳适合的存储格局

  1. 在Hive SQL的create table语句中,能够应用stored as ...指定表的存储格局。
    Hive表反对的存储格局有TextFileSequenceFileRCFileAvroORCParquet等。
    存储格局个别须要依据业务进行抉择,在咱们的实操中,绝大多数表都采纳TextFileParquet两种存储格局之一。
  2. TextFile是最简略的存储格局,它是纯文本记录,也是Hive的默认格局,尽管它的磁盘开销比拟大,查问效率也低,但它更多地是作为跳板来应用。
  3. RCFileORCParquet等格局的表都不能由文件间接导入数据,必须由TextFile来做直达。
  4. ParquetORC都是Apache旗下的开源列式存储格局。列式存储比起传统的行式存储更适宜批量OLAP查问,并且也反对更好的压缩和编码。
  5. 咱们抉择Parquet的起因次要是它反对Impala查问引擎,并且咱们对updatedelete事务性操作需要很低。

Hive的小文件

什么状况下会产生小文件?

  1. 动静分区插入数据,产生大量的小文件,从而导致map数量剧增
  2. reduce数量越多,小文件也越多,有多少个reduce,就会有多少个输入文件,如果生成了很多小文件,那这些小文件作为下一次工作的输出
  3. 数据源自身就蕴含大量的小文件

小文件有什么样的危害?

  1. 从Hive的角度看,小文件会开很多map,一个map开一个java虚拟机jvm去执行,所以这些工作的初始化,启动,执行会节约大量的资源,重大影响性能
  2. 在hdfs中,每个小文件对象约占150byte,如果小文件过多会占用大量内存,这样NameNode内存容量重大制约了集群的扩大

    • 每个hdfs上的文件,会耗费128字节记录其meta信息,所以大量小文件会占用大量内存

如何防止小文件带来的危害?

从小文件产生的途经就能够从源头上管制小文件数量

  1. 应用Sequencefile作为表存储格局,不要用textfile,在肯定水平上能够缩小小文件
  2. 缩小reduce的数量(能够应用参数进行管制)
  3. 少用动静分区,用时记得按distribute by分区

    对于已有的小文件

  4. 应用hadoop archive命令把小文件进行归档,采纳archive命令不会缩小文件存储大小,只会压缩NameNode的空间应用
  5. 重建表,建表时缩小reduce数量

我是 fx67ll.com,如果您发现本文有什么谬误,欢送在评论区探讨斧正,感谢您的浏览!
如果您喜爱这篇文章,欢送拜访我的 本文github仓库地址,为我点一颗Star,Thanks~ :)
转发请注明参考文章地址,非常感谢!!!