2、谓词下推
3、sort by 替换order by
4、group by 代替distinct
5、group by 配置调整
map 端预聚合:set hive.map.aggr=true set hive.groupby.mapaggr.checkinterval=100000
倾斜均衡配置项:set hive.groupby.skewindate=true
6、join优化
6.1 大小表,小表前置
6.2 多表Join时key相同
6.3 利用mapjoin特性
6.4 分桶表 mapjoin
6.5 倾斜均衡配置项:
设置hive.optimize.skewjoin=true,开启后,在join过程中hive会将计数超过阈值hive.skewjoin.key(默认100000)的倾斜key对应的行临时写进文件中,然后再启动另一个job做map join生成结果。通过hive.skewjoin.mapjoin.map.task参数还可以控制第二个job的mapper数量,默认10000.
6.7 优化sql处理join数据倾斜
6.7.1、空值或无意义的值:若不需要空值数据,就提前写到where语句过滤掉,如果需要保留的话,将空值key用随机方式打散。
6.7.2、单独处理倾斜key
6.7.3、不同数据类型,join的关联字段类型不一样,导致耗时长,所以需要注意做类型转换(join关联字段,一个是int,一个是string,,计算key的hash值时默认时int类型做的,这样导致所有真正的string类型的key都分配到一个reducer上了)
6.7.4、mapjoin的小表比较大的时候,,无法直接使用mapjoin,则 select/*+mapjoin(b)*/ from a left join ( select /*+mapjoin (b)*/ from b inner join a )
6.8、mapreduce 优化
6.8.1、调整mapper数
mapper数量与输入文件的split数息息相关。如果想减少mapper数,就适当提高mapred.min.split.size,split数就减少了;如果想增大mapper数,除了降低maperd.min.split.size之外,也可以提高mapred.map.task;一般来讲,如果输入文件是少量大文件,就减少mapper数;如果是大量非小文件,就增大mapper数,如果是小文件,就喝吧小文件
6.8.2 调整reducer数
使用参数mapred.reduce.task可以直接设定reducer数量,如果不设置的话,hive会自行推测,推测逻辑如下:
参数hive.exec.reducers.bytes.per.reducer.设定每个reducer能够处理的最大的数据量,默认时1G
参数hive.exec.reducers.max设定每个job的最大的reducer数量,默认时999或者1009
得到reducer数:reducers_num=min(total_input_size/reducers.bytes.per.reducer,reducers.max)
reducer数量与输出文件的数量相关,如果reducer数太多,会产生大量小文件,对hdfs造成压力,如果reducer数太少,每个reducer要处理很多数据,容易拖慢运行时间或造成oom
6.8.3 合并小文件
输入阶段合并:需要更改hive的输入文件格式,即参数hive.input.format,默认值是org.apache.hadoop.hive.ql.io.hiveiputformat,我们该成org.apache.hadoop.hive.ql.io.combinehiveinputformat.
这样比调整mapper数时,又多出两个参数,分别是mapred.min.split.size.per.node和mapred.min.split.size.per.rack,含义是单节点和单机架上的最小split大小。如果发现又split大小小于这两个默认值100MB,则会进行合并
输出阶段合并:直接将hive.merge.mapfiles和hive.merge.mapredfiles都设置为true即可。
hive.merge.mapfiles表示将map-only任务的输出合并
hive.merge.mapredfiles表示将map-reduce任务的输出合并
另外hive.merge.size.per.task可以指定每个task输出后合并文件大小的期望值
hive.merge.size.smallfiles.avgsize可以指定所有输出文件大小的均值阈值,默认时1G
6.9 启用压缩
压缩job的中间结果数据和输出数据,可以少量CPU时间节省出很多空间。压缩方式一般选择snappy,效率最高,要启用中间压缩,需要设定:
hive.exec.compress.intermediate为true,同时指定压缩方式hive.intermediate.compression.code为org.apache.hadoop.io.compress.snappycode.
另外,参数hive.intermediate.compression.type可以选对块block还是对记录record压缩,block压缩率比较高,输出压缩的配置基本相同:打开hive.exec.compress.output
6.10 jvm重用
在mr job中,默认时每执行一个task就会启动一个jvm,如果task非常小而且碎,那么jvm启动和关闭耗时都会比较长。可以通过调节参数mapred.job.reuse.jvm.num.task来重用。例如将这个参数设置为5,那么久代表同一个mr job中顺序执行的5各task可以重复使用一个jvm,减少启动和关闭开销,但是他对不同mr job的task无效
6.11 采用合适的存储格式
6.12 数据倾斜
数据倾斜原因:1、join 倾斜 2、聚合倾斜
group by 倾斜: group by 字段中某个字段的值过多,导致处理这个值得reduce耗时很久
解决方法:set hive.map.aggr=true -- 表示开启map端聚合
set hive.groupby.skewindata=true 注意:只能对单个字段聚合 , 生成两个map job ,第一个map job中map输出结果随机分布到reduce中,每个reduce做部分聚合 *** 作,并输出结果,这样相同的groub key有可能被分发到不同的reduce中,从而达到负载均衡的目的;第二个map job再根据预处理的数据结果按照group by key分布到reduce中,这个过程可以保证相同的key被分到同一个reduce中,最后完成最终的聚合 *** 作
6.13 优化in、exists语句
使用left semi join 替换in 、exists
6.14 合并 mapreduce *** 作
multi-group by 是hive的一个非常好的特性,它使得hive中利用中间结果变更非常方便
例如:
from ( select a.status,b.school from status_update a join profilees b on (a.userid=b.suerid)) subq1
insert overwirte table a1 partition(ds='2021-03-07')
select subq1.school,count(1) group by subq1.school
insert overwrite table b1 partition(ds='2021-03-07')
select subq1.status,count(1) group by subq1.status
上述语句使用了multi-group by特性联系group by 2次数据,使用不同的group by key,这一特性可以减少一次mapreduce *** 作
1数据存储及压缩优化
针对hive中表的存储格式通常有textfile和orc,压缩格式一般使用snappy。相比于 textfile格式存储,orc占有更少的存储。因为hive底层使用MR计算架构,数据流是hdfs到磁盘再到hdfs,而且会有很多次IO读写 *** 作,所以使用orc数据格式和snappy压缩策略可以降低IO读写,还能降低网络传输量,这样在一定程度上可以节省存储空间,还能提升hql的执行效率;
2 Hive Job优化
① 调节Jvm参数,重用Jvm;
② 合理设置Map个数;
③ 合理设置Reduce个数;
3 Sql语法优化
① 建表优化 :
1) Hive创建表的时候,可以建分区表,分桶表;
2) Hive创建表的时候,可以指定数据存储格式:TextFile、SequenceFile、RCfile 、ORCfile;
② 查询时优化 :
1) 列裁剪,在查询时只读取需要的列,避免全列扫描,不要使用select * from table;
2) 分区裁剪:在查询时只读取需要分区的数据,避免全表扫描;
3) 开启谓词下推:set hive.optimize.ppd = true,默认是true:
a. 将Sql语句中的where谓词逻辑都尽可能提前执行,减少下游处理的数据量;
4) 大表join小表:
a. 开启MapJoin:set hive.auto.convert.join=true:
b. MapJoin是将Join双方比较小的那个表直接分发到各个Map进程的内存中,在 Map进程中进行Join *** 作, 这样就不用进行Reduce步骤 ,从而提高了速度( 大表left join小表才有效 ,小表left join大表会失效);
5) 大表join大表:
a. SMB Join :Sort Merge Bucket Join(数据不仅分桶了,而且每个桶数据是排好序了);
b. 开启SMB Join之后,底层是根据两个表join字段进行分桶存储,这样的话,两张表就变为了基于桶之间join关联查询,而不是基于整张表的join,减少了笛卡尔积;
6) 少用in,用left semi join替代in:
a. 原始写法:select a.id, a.name from a where a.id in (select b.id from b);
b. 用join改写:select a.id, a.name from a join b on a.id = b.id;
c. left semi join改写:select a.id, a.name from a left semi join b on a.id = b.id;
7) 用union all代替union,因为union all不需要去重,也不需要排序,效率高于union;
(每天1小题,进步1点点)
Hive用的好,才能从数据中挖掘出更多的信息来。用过hive的朋友,我想或多或少都有类似的经历:一天下来,没跑几次hive,就到下班时间了。Hive在极大数据或者数据不平衡等情况下,表现往往一般,因此也出现了presto、spark-sql等替代品。这里重点讲解hive的优化方式,例如
一. 表连接优化
二. 用insert into替换union all
如果union all的部分个数大于2,或者每个union部分数据量大,应该拆成多个insert into 语句,实际测试过程中,执行时间能提升50%。示例参考如下:
可以改写为:
三. order by &sort by
order by : 对查询结果进行全局排序消耗时间长,需要set hive.mapred.mode=nostrict
sort by : 局部排序,并非全局有序,提高效率。
四. transform+python
一种嵌入在hive取数流程中的自定义函数,通过transform语句可以把在hive中不方便实现的功能在python中实现,然后写入hive表中。示例语法如下:
如果除python脚本外还有其它依赖资源,可以使用ADD ARVHIVE。
五. limit 语句快速出结果
一般情况下,Limit语句还是需要执行整个查询语句,然后再返回部分结果。有一个配置属性可以开启,避免这种情况—对数据源进行抽样
缺点:有可能部分数据永远不会被处理到
六. 本地模式
对于小数据集,为查询触发执行任务消耗的时间>实际执行job的时间,因此可以通过本地模式,在单台机器上(或某些时候在单个进程上)处理所有的任务。
可以通过设置属性hive.exec.mode.local.auto的值为true,来让Hive在适当的时候自动启动这个优化,也可以将这个配置写在$HOME/.hiverc文件中。
当一个job满足如下条件才能真正使用本地模式:
七. 并行执行
Hive会将一个查询转化为一个或多个阶段,包括:MapReduce阶段、抽样阶段、合并阶段、limit阶段等。默认情况下,一次只执行一个阶段。 不过,如果某些阶段不是互相依赖,是可以并行执行的。
会比较耗系统资源。
八. 调整mapper和reducer的个数
假设input目录下有1个文件a,大小为780M,那么hadoop会将该文件a分隔成7个块(6个128m的块和1个12m的块),从而产生7个map数
假设input目录下有3个文件a,b,c,大小分别为10m,20m,130m,那么hadoop会分隔成4个块(10m,20m,128m,2m),从而产生4个map数。
即如果文件大于块大小(128m),那么会拆分,如果小于块大小,则把该文件当成一个块。
map执行时间:map任务启动和初始化的时间+逻辑处理的时间。
减少map数
若有大量小文件(小于128M),会产生多个map,处理方法是:
前面三个参数确定合并文件块的大小,大于文件块大小128m的,按照128m来分隔,小于128m,大于100m的,按照100m来分隔,把那些小于100m的(包括小文件和分隔大文件剩下的)进行合并。
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat– 执行前进行小文件合并。
增加map数
当input的文件都很大,任务逻辑复杂,map执行非常慢的时候,可以考虑增加Map数,来使得每个map处理的数据量减少,从而提高任务的执行效率。
set mapred.reduce.tasks=?
一般根据输入文件的总大小,用它的estimation函数来自动计算reduce的个数:reduce个数 = InputFileSize / bytes per reducer
九. 严格模式
十. 数据倾斜
表现:
任务进度长时间维持在99%(或100%),查看任务监控页面,发现只有少量(1个或几个)reduce子任务未完成。因为其处理的数据量和其他reduce差异过大。单一reduce的记录数与平均记录数差异过大,通常可能达到3倍甚至更多。 最长时长远大于平均时长。
原因:
解决方案:参数调节
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)