总结了一下在以往工作中,对于Hive SQL
调优的一些理论利用,是日常积攒的一些优化技巧,如有出入,欢送在评论区留言探讨~
EXPLAIN 查看执行打算
建表优化
分区
- 分区表基本操作,partitioned
- 二级分区
- 动静分区
分桶
- 分桶表基本操作,clustered
- 分桶表次要是抽样查问,找出具备代表性的后果
抉择适合的文件格式和压缩格局
- LZO,拉兹罗
- Snappy
- 压缩速度快,压缩比高
HiveSQL语法优化
单表查问优化
列裁剪和分区裁剪,全表和全列扫描效率都很差,生产环境相对不要应用
SELECT *
,所谓列裁剪就是在查问时只读取须要的列,分区裁剪就是只读取须要的分区- 与列裁剪优化相干的配置项是
hive.optimize.cp
,默认是true - 与分区裁剪优化相干的则是
hive.optimize.pruner
,默认是true - 在
HiveSQL
解析阶段对应的则是ColumnPruner
逻辑优化器
- 与列裁剪优化相干的配置项是
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;
Vectorization,矢量计算技术,通过设置批处理的增量大小为1024行单次来达到比单行单次更好的效率
# 开启矢量计算 set hive.vectorized.execution.enabled = true;# 在reduce阶段开始矢量计算 set hive.vectorized.execution.reduce.enabled = true;
- 多重模式,一次读取屡次插入,同一张表的插入操作优化成先
from table
再insert
- in/exists或者join用
left semi join
代替(为什么代替扩大一下~)
多表查问优化
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;
谓词下推(十分要害的一个优化),将
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;
Map Join,
map join
是指将join
操作两方中比拟小的表间接散发到各个map
过程的内存中,在map
中进行join
的操作。map join
特地适宜大小表join
的状况,Hive会将build table
和probe table
在map
端间接实现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;
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;
多表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;
- 笛卡尔积,在生产环境中严禁应用
其余查问优化
Sort By 代替 Order By,HiveQL中的
order by
与其余sql
方言中的性能一样,就是将后果按某字段全局排序,这会导致所有map
端数据都进入一个reducer
中,
在数据量大时可能会长工夫计算不完。如果应用sort by
,那么还是会视状况启动多个reducer进行排序
,并且保障每个reducer
内部分有序。
为了管制map
端数据调配到reducer
的key
,往往还要配合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;
- Group By代替Distinct,当要统计某一列的去重数时,如果数据量很大,
count(distinct)
就会十分慢,起因与order by
相似,count(distinct)
逻辑只会有很少的reducer
来解决。然而这样写会启动两个mr工作
(单纯distinct只会启动一个),
所以要确保数据量大到启动mr工作
的overhead
远小于计算耗时,才思考这种办法,当数据集很小或者key
的歪斜比拟显著时,group by
还可能会比distinct
慢
数据歪斜
留神要和数据适量的状况辨别开,数据歪斜是大部分工作都曾经执行结束,然而某一个工作或者少数几个工作,始终未能实现,甚至执行失败,
而数据适量,是大部分工作都执行的很慢,这种状况须要通过裁减执行资源的形式来加快速度,大数据编程不怕数据量大,就怕数据歪斜,一旦数据歪斜,重大影响效率
单表携带了 Group By 字段的查问
工作中存在
group by
操作,同时聚合函数为count
或sum
,单个key
导致的数据歪斜能够这样通过设置开启map
端预聚合参数的形式来解决# 是否在map端聚合,默认为trueset hive.map.aggr = true;# 在map端聚合的条数set hive.groupby.mapaggr.checkintervel = 100000;# 有数据歪斜的时候开启负载平衡,这样会生成两个mr工作set hive.groupby.skewindata = true;
工作中存在
group by
操作,同时聚合函数为count
或sum
,多个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 集中
设置参数减少
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;
- 应用
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
类型进行关联,关联时候以小类型作为分区,这里int
、string
会到一个reduceTask
中,如果数据量多,会造成数据歪斜
# 能够通过转换为同一的类型来解决cast(user.id as string)
独自解决歪斜key
这其实是下面解决空值办法的拓展,不过歪斜的key
变成了有意义的,一般来讲歪斜的key
都很少,咱们能够将它们抽样进去,
对应的行独自存入长期表中,而后打上一个较小的随机数前缀(比方0~9
),最初再进行聚合
Hive Job 优化
Hive Map 优化
Map数量多少的影响
Map数过大
map
阶段输入文件太小,产生大量小文件- 初始化和创立
map
的开销很大
Map数太小
- 文件解决或查问并发度小,
Job
执行工夫过长 - 大量作业时,容易梗塞集群
- 文件解决或查问并发度小,
管制Map数的准则
依据理论状况,管制map
数量须要遵循两个准则
- 第一是使大数据量利用适合的
map
数 - 第二是使单个
map
工作解决适合的数据量
简单文件适当减少Map数
- 当
input
的文件都很大,工作逻辑简单,map
执行十分慢的时候,能够思考减少map
数,来使得每个map
解决的数据量缩小,从而进步工作的执行效率 - 那么如何减少
map
的数量呢?在map
阶段,文件先被切分成split
块,而后每一个split
切片对应一个Mapper工作
,FileInputFormat
这个类先对输出文件进行逻辑上的划分,以128m
为单位,将原始数据从逻辑上宰割成若干个split
,每个split
切片对应一个mapper工作
,
所以说缩小切片的大小就可减少map
数量 - 能够根据公式计算
computeSliteSize(Math.max(minSize, Math.min(maxSize, blockSize))) = blockSize = 128m
- 执行语句:
set mapreduce.input.fileinputformat.split.maxsize = 100;
小文件进行合并缩小Map数
为什么要进行小文件合并?因为如果一个工作有很多小文件(远远小于块大小128m),则每个小文件也会被当做一个块,用一个map
工作来实现,
而一个map
工作启动和初始化的工夫远远大于逻辑解决的工夫,就会造成很大的资源节约,同时可执行的map
数是受限的
两种形式合并小文件
在
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;
在
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数量
- 相当于在
map
端执行combiner
,执行命令:set hive.map.aggr = true;
combiners
是对map
端的数据进行适当的聚合,其益处是缩小了从map
端到reduce
端的数据传输量- 其作用的实质,是将
map
计算的后果进行二次聚合,使Key-Value<List>
中List
的数据质变小,从而达到缩小数据量的目标
揣测执行
- 在分布式集群环境下,因为程序Bug(包含Hadoop自身的bug),负载不平衡或者资源散布不均等起因,会造成同一个作业的多个工作之间运行速度不统一,
有些工作的运行速度可能显著慢于其余工作(比方一个作业的某个工作进度只有50%,而其余所有工作曾经运行结束),则这些工作会拖慢作业的整体执行进度 - Hadoop采纳了
揣测执行(Speculative Execution)
机制,它依据肯定的法令揣测出拖后腿的工作,并为这样的工作启动一个备份工作,
让该工作与原始工作同时解决同一份数据,并最终选用最先胜利运行实现工作的计算结果作为最终后果 - 执行命令:
set mapred.reduce.tasks.speculative.execution = true; # 默认是true
- 当然,如果用户对于运行时的偏差十分敏感的话,那么能够将这些性能敞开掉,如果用户因为输出数据量很大而须要执行长时间的
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数量多少的影响
- 同
map
一样,启动和初始化reduce
也会耗费工夫和资源 - 另外,有多少个
reduce
,就会有多少个输入文件,如果生成了很多个小文件,那么如果这些小文件作为下一个工作的输出,则也会呈现小文件过多的问题
管制Reduce数的准则
和map
一样,管制reduce
数量须要遵循两个准则
- 第一是使大数据量利用适合的
reduce
数 - 第二是使单个
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的个数个别通过程序主动推定,而不人为干预,因为人为管制的话,如果使用不当很容易造成后果不精确,且升高执行效率
通过调整每个
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
间接调整每个
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
参数值的状况外,还有以下起因:
没有
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";留神防止这样状况的产生
- 用了
Order by
排序,因为它会对数据进行全局排序,所以数据量特地大的时候效率非常低,尽量避免 - 有笛卡尔积,生产环境必须严格防止
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种语句是:
- 查问分区表时不限定分区列的语句
- 两表join产生了笛卡尔积的语句
- 用order by来排序但没有指定limit的语句
JVM重用
- 次要用于解决小文件过多的时候
- 在
mr 工作
中,默认是每执行一个task
就启动一个JVM
,如果task
十分小而碎,那么JVM
启动和敞开的耗时就会很长 - 能够通过调节参数
mapred.job.reuse.jvm.num.tasks
来重用 - 例如将这个参数设成5,那么就代表同一个
mr 工作
中程序执行的5个task
能够重复使用一个JVM
,缩小启动和敞开的开销,但它对不同mr 工作
中的task
有效
启用压缩
压缩job的两头后果数据和输入数据,能够用大量CPU工夫节俭很多空间,压缩形式个别抉择Snappy,效率最高。
要启用两头压缩,须要设定hive.exec.compress.intermediate
为true,
同时指定压缩形式hive.intermediate.compression.codec
为org.apache.hadoop.io.compress.SnappyCodec
。
另外,参数hive.intermediate.compression.type
能够抉择对块(BLOCK)
还是记录(RECORD)
压缩,BLOCK的压缩率比拟高。
输入压缩的配置基本相同,关上hive.exec.compress.output
即可
采纳适合的存储格局
- 在Hive SQL的
create table
语句中,能够应用stored as ...
指定表的存储格局。
Hive表反对的存储格局有TextFile
、SequenceFile
、RCFile
、Avro
、ORC
、Parquet
等。
存储格局个别须要依据业务进行抉择,在咱们的实操中,绝大多数表都采纳TextFile
与Parquet
两种存储格局之一。 TextFile
是最简略的存储格局,它是纯文本记录,也是Hive的默认格局,尽管它的磁盘开销比拟大,查问效率也低,但它更多地是作为跳板来应用。RCFile
、ORC
、Parquet
等格局的表都不能由文件间接导入数据,必须由TextFile
来做直达。Parquet
和ORC
都是Apache旗下的开源列式存储格局。列式存储比起传统的行式存储更适宜批量OLAP查问
,并且也反对更好的压缩和编码。- 咱们抉择
Parquet
的起因次要是它反对Impala查问引擎
,并且咱们对update
、delete
和事务性操作
需要很低。
Hive的小文件
什么状况下会产生小文件?
- 动静分区插入数据,产生大量的小文件,从而导致map数量剧增
- reduce数量越多,小文件也越多,有多少个reduce,就会有多少个输入文件,如果生成了很多小文件,那这些小文件作为下一次工作的输出
- 数据源自身就蕴含大量的小文件
小文件有什么样的危害?
- 从Hive的角度看,小文件会开很多map,一个map开一个java虚拟机jvm去执行,所以这些工作的初始化,启动,执行会节约大量的资源,重大影响性能
在hdfs中,每个小文件对象约占150byte,如果小文件过多会占用大量内存,这样NameNode内存容量重大制约了集群的扩大
- 每个hdfs上的文件,会耗费128字节记录其meta信息,所以大量小文件会占用大量内存
如何防止小文件带来的危害?
从小文件产生的途经就能够从源头上管制小文件数量
- 应用Sequencefile作为表存储格局,不要用textfile,在肯定水平上能够缩小小文件
- 缩小reduce的数量(能够应用参数进行管制)
少用动静分区,用时记得按distribute by分区
对于已有的小文件
- 应用hadoop archive命令把小文件进行归档,采纳archive命令不会缩小文件存储大小,只会压缩NameNode的空间应用
- 重建表,建表时缩小reduce数量
我是 fx67ll.com,如果您发现本文有什么谬误,欢送在评论区探讨斧正,感谢您的浏览!
如果您喜爱这篇文章,欢送拜访我的 本文github仓库地址,为我点一颗Star,Thanks~ :)
转发请注明参考文章地址,非常感谢!!!