Hive性能调优实战 总结三

第7章 Hive数据处理模式

过滤模式

  • 普通的where的在map端过滤,map端的任务在执行时尽可能将计算逻辑发送到数据所在的机器中执行,多机同时过滤。对一个作业应尽量将其放在前面进行数据过滤

  • having子句过滤发生在数据聚合后,MR引擎中在Reduce阶段过滤,在Reduce 和Group by操作之后

  • distinct 在Reduce阶段,和用group by的执行计划类似,分组聚合的方式不是Hive去重的唯一方式,有时还会用到Hash表

  • multi-group-by-insert语法 ,表在读取一次后,可以被多个查询语句使用

    from student_tb_txt
    insert into table student_stat partition(tp)
    select s_age,max(s_birth) stat, 'max' tp
    group by s_age
    insert into table student_stat partition(tp)
    select s_age,min(s_birth) stat, 'min' tp
    group by s_age
    
  • 分区列筛选,能够在Map之前进行数据过滤,得益于分区表存储格式——分区表|分区列(part = ?)

  • 分桶列筛选,能够对数据重新组织,快速过滤不需要的文件,分区是对目录的过滤**,分桶是对文件的过滤**,记录所存储的桶 = mod(hash(分桶列的值),16) 把所有文件按照hash值分到16个桶

  • 在列过滤中,ORC/Parquet格式中存储了文件定义的Schema,可以直接读取表所在的列,比一般的格式先取整行数据,再通过列的偏移量得到对应的列值更快。

聚合模式

  • distinct模式,在map端开启聚合,会在Map中进行数据局部聚合,再在Reduce中开启全局聚合
  • **COUNT(*)和COUNT(1)会得到包含NULL的数据行数,在数据统计时,不会读取表中的数据,只是使用到HDFS文件中每一行的行偏移量(**HDFS添加的),
  • 而COUNT(<列名>)会得到NULL之外的数据行数。针对列的计数,涉及字段的筛选和数据序列化和反序列化
  • 在ORC文件中,这三者相差不多
  • 可计算中间结果的聚合模式,sum、max、min、avg等 在本地处理阶段被聚合成少量数据,之后再做计算可以减少网络和下游节点处理的数据量
  • 不可计算中间结果的聚合模式,collect_list collect_set,和前面的类似,不同的是Map阶段Reduce Output Operator 中 value输出的是个集合数组

连接模式

  • Repartition连接,发生在shuffle和Reduce阶段,Map读取两个表的数据,将按照连接条件发往相同的Reduce,在Reduce中计算合并

  • Replication连接(map join),发生在Map阶段,减少从HDFS中读取表的次数,在操作时将一个表的数据复制到各个Map任务所在的节点并存储在缓存中,适用于有小表的情况

  • map join

    • 先启动一个作业读取小表的数据,在内存中构建哈希表,把哈希表写入本地磁盘,然后把哈希表上传到HDFS并添加到分布式缓存中。
    • 再启动一个任务读取B表的数据,在连接时map会获取缓存中的数据并存入哈希表中,B表会和哈希表的数据匹配
    • 时间复杂度是O(1)
    • 开启hint命令 set hive.ignore.mapjoin.hint = false /*+mapjoin(b)*/ hint操作
    • 推荐:
      • hive.auto.convert.join = true 是否根据文件大小把repartition 转为 replication;
      • hive.smalltable.filesize = 25000000 byte 小表数据小与阈值时,将转换 和上面的一起用
  • 使用桶的Map连接要保证连接的两张表的分桶数之间是倍数关系

  • 倾斜连接

    • set hive.optimize.skewjoin = true 是否优化有倾斜键的表连接

    • set hive.skewjoin.key = 100000 相同键的行数多于指定值 认为该键是倾斜连接键

    • -- 可以通过创建表时制定数据倾斜键,将制定的数据键分割成单独的数据文件或目录
      create table a(s_no string,s_score bigint)
      skewed by (s_score) on (99,97)
      stored as directories
      
  • 表连接与基于成本的优化器

    • 一开始 Hive使用的是基于规则的优化器 Rule Based Optimizer
    • 后来使用Calcite 是一个开源的基于成本优化器(CBO),根据Hive收集到表、列的统计信息,估算成本
    • CBO优点
      • 表连接的顺序优化,不需要特别制定大小表的顺序,会根据收到的情况,自动算出
      • Bushy Tee连接的执行,可以估算出每个表连接的组合,两两结合生成中间结果,未引入的时候所有表连接都被表示成左深树,内部节点都至少有一个叶子作为子节点
      • 简化表的连接,多表连接时,识别并抽取相同的连接谓词,构造一个隐式的连接谓词作为替换

第8章 YARN日志

ResourceManager Web UI 界面

  • 一般来说端口8088
  • Scheduler 中 比较重要的 Application Queues
  • 主要的性能瓶颈定位

JobHistory Web UI 界面

  • 一般来说端口 19888

查看集群状态

  • Cluster中的About | metrics | nodes 链接

第9章 数据存储

数据格式

  • Text File format : 默认格式,数据不做压缩,磁盘开销大,数据解析开销大。在反序列化过程中,必须逐个字符判断是不是分隔符 和行结束符,因此反序列化开销会比SequenceFile高几十倍
  • Sequence File format
    • SequenceFile 是 Hadoop API 提供的一种二进制文件支持,其具有使用方便、可分割、可压缩的特点
    • SequenceFile 支持三种压缩选择:NONE, RECORD, BLOCK。 Record 压缩率低,一般建议使用 BLOCK 压缩。
    • 面向行:在一起存储的同一行数据是连续存储
  • ORCFile : 对RCFile做了一些优化,支持各种复杂的数据类型 性能比较好
    • 将数据先按行进行切分,一个行组内包含若干行,每一行组再按列进行存储,ORC 将行的集合存储在一个文件中,并且集合内的行数据将以列式存储。采用列式格式,压缩非常容易,从而降低了大量的存储成本。
    • ORC 会创建索引(文件级、条带级、行组级(在stripe中每10000行构成一个行组)),当查询的时候会很快。当查询时,会查询特定列而不是查询整行,因为记录是以列式存储的。
    • 由三部分构成:
      • 条带stripe:ORC文件存储数据的地方
      • 文件脚注:包含文件stripe的列表包括行数,数类型,最大值等
      • postscript:压缩参数和压缩大小
    • ORC文件也是以二进制方式存储的,所以是不可以直接读取
  • RCfile format : RCFILE 是一种行列存储相结合的存储方式,数据按行分块,每块按列存储。首先,其将数据按行分块,保证同一个 record 在一个块上,避免读一个记录需要读取多个 block。其次,块数据列式存储,有利于数据压缩和快速的列存取。RCFile 目前没有性能优势,只有存储上能省 10% 的空间。
  • Parquet :
    • 列式数据存储。 查询比较快
    • Parquet支持嵌套的数据模型,每一个数据模型的schema包含多个字段,每一个字段有三个属性:重复次数、数据类型和字段名
    • 二进制方式存储的,是不可以直接读取和修改的
  • AVRO : avro Schema 数据序列化。

数据归档

启动数据归档

set hive.archive.enable = true; set hive.archive.har.parentdir.settable=true;

归档后的最大文件大小

set har.partfile.size = 109951162776

对分区执行归档的命令

alter table tablename archive partition(partition_col = partition_val)

还原成普通分区

alter table tablename unarchive partition(partition_col = partition_val)

  • 大量的小文件可以通过 Hadoop归档 (Hadoop archive)把文件归并成几个较大的文件
  • 归并后的分区会先创建一个data.har 目录,包含索引( _index 和 _masterindex )和数据(part-*)
  • 归档后不会对数据进行压缩

@第10章 发现并优化问题

收集表的元数据 : analyze table 表名 compute statistics (noncan)

收集字段的元数据 : analyze table 表名 compute statistics for columns

收集分区的元数据 : analyze table 表名 partition (分区列 = 分区值) compute statistics

收集所有分区的列的元数据 : analyze table 表名 partition(分区列) compute statistics for columns

@监控普通表存储的文件的平均大小

--整体逻辑通过 DBS找到对应库下面的表TBLS
--再通过TBLS找到每个表对应的表属性,取得totalSize和numFiles两个属性
select tbl_ name, avgfilesize 'fileSize (MB)'
from (
	select tp.totalSize/(1024*1024)/numFiles avgfilesize, TBL_NAME
	from DBS d
	inner join TBLS t on d.DB_ID = t.DB_ID -- DBS 的主键DB_ID*
	left join 
  (
		select TBL_ID,
		max (case PARAM_KEY when 'numFiles'then PARAM_VALUE else 0 end) numFiles, --每个表存储的文件个数
		max (case PARAM_KEY when 'totalSize'then PARAM_VALUE else 0 end) totalSize --文件存储的大小
		from TABLE_PARAMS --TABLE PARAMS 记录的表属性
    GROUP BY TBL_ID
  )tp
  on t.TBL_ID = tp.TBL_ID
  where d.NAME = '数据库名' and tp.numFiles is not null and tp.numFiles > 0
 )a
 where avgfilesize > hdfs的文件块大小*2

监控大表不分区的表

/*监控大表不分区的表*/
select t.TBL_NAME '表名',d.'NAME' '库名',totalsize /1024/1024/1024 '文件大小(GB)'
from DBS d
inner join TBLS t on d.DB ID= t.DB ID
inner join(
  select TBL_ID,
  max (case PARAM_KEY when 'totalSize' then PARAM_VALUE else 0 end) totalSize
  from TABLE_PARAMS
	GROUP BY TBL_ID
)tp 
on t.TBL_ID  = tp.TBL_ID
left join(
	select distinct TBL_ID from PARTITIONS -- 分区数据
)part
on t.TBL_ID = part.TBL_ID
where d.NAME = '数据库名' and part.TBL_ID is null and totalSize/1024/1024/1024 > 30

@监控分区数据不均匀的表

select TBL_NAME, max (totalSize) , min(totalSize) , avg (totalSize)
from
(
  select pp.totalSize, TBL_NAME, part.PART_NAME
  from DBS d
  inner join TBLS t on d.DB_ID=t.DB_ID
  inner join PARTITIONS part on t.TBL_ID=part.TBL_ID
  inner join 
  (
    select PART_ID,
    max (case PARAM_KEY when 'totalSize ' then PARAM_VALUE else 0 end)/1024/1024 totalSize
    from PARTITION_PARAMS -- 分区属性
    GROUP BY PART_ID
  ) pp on part.PART ID=pp.PART ID
  where d.NAME= 'default'
  and pp.totalSize is not null and pp. totalSize > 0
)
a group by TBL_NAME
having max (totalSize) > avg (totalSize)*5

@查询表字段的空值率

-- 表字段的空值率,以及重复字段所占的比例
select t.TBL_NAME '表名', d.NAME '库名', tcs.COLUMN_NAME '字段名',
				NUM_NULLS*1.0/tp.numRows '空值率',
				1-NUM_DISTINCTS*1.0/t.numRows '重复字段占比'
from DBS d
inner join TBLS t on d.DB_ ID = t.DB_ID
inner join TAB_COL_STATS tcs on t.TBL_ID=tcs.TBL_ID
left join
(
	select TBL_ID,
  max (case PARAM_KEY when 'numRows' then PARAM_VALUE else 0 end) numsRows
  from TABLE_PARAMS
	GROUP BY TBL_ID
)tp
on t.TBL_ID = tp.TBL_ID
where d.NAME = '数据库名'  and t.TBL_NAME = '表名'

监控当前集群状态

获取集群的状态信息

get http:// /ws/v1/cluster/info

获取集群任务的状态信息

get http:// /ws/v1/cluster/metrics

获取提交到集群所有任务的运行信息

get http:// /ws/v1/cluster/apps

get http:// /ws/v1/cluster/apps?user=hue

可使用参数特定查询:states(处于特定状态)、finalStatus(处于final状态)、user(用户)、 queue(指定队列) startedTimeBegin(从指定时间开始运行的任务)、 startedTimeEnd 、 finishedTime、任务ID号

获取当前资源调度的分配信息

get http:// /ws/v1/cluster/scheduler

# 用python获取
import requests
import json
clustr_status_url = 'http://<rm http address:port> /ws/v1/cluster'
res = requests.get(clustr_status_url)
print res.content
ct = json.loads(res.content)
print ct.get('clusterInfo').get('state')

@定位性能瓶颈

HiveServer2 WebUI 排除大数据组件的问题

  • 提供的作业分析工具 http://主机名:10002/hiveserver2.jsp

  • 端口默认:10002

  • Drill down 中 Performance Logging 中

    • 获取元数据所用的时间
    • 任务提交到集群后运行的消耗

Job OverView 排查长时间等待调度

  • 可以查看作业是否存在长时等待

  • submitted 和 started 启动间隔,间隔长需要查看scheduler的信息 ,队列资源是否过载

Map任务读取小任务

  • 如果一个作业读取的文件多数是小文件,没有配置合并读取小文件,意味着每读取一个文件都要启动一个Java进程
  • 追踪过程:FINISHED的作业 --> Tracking URL : History --> Map --> name --> status
  • xxxxxxxx/part-001-xxxxxx:0+214149 表示读取了214149bytes的文件内容

每个Map最小输入大小(这个值决定了合并后文件的数量)

set mapred.min.split.size=256000000;

数据倾斜

开启Map端聚合参数设置

set hive.map.aggr=true

进行负载均衡

set hive.groupby.skewindata = true

调整reduce所执行的内存大小,使用

set mapreduce.reduce.memory.mb

  • 单个节点任务所处理的数据量远大于同类型任务,可能的原因

  • 任务读取大文件

    • 读取压缩的不可分割的大文件
  • 任务需要处理大量相同键的数据

    • 数据含有大量无意义的数据,空值NULL等
    • 还有倾斜数据在进行聚合计算时无法聚合中间结果,大量数据要经过shuffle处理,引起数据倾斜,
    • 数据在计算时做多维数据集合,导致维度膨胀引起的数据倾斜,产出的数据膨胀,导致内存溢出
    • 两表进行Join,含有大量相同的倾斜数据键
  • 不可拆分大文件引起的数据倾斜

    • 对文件使用GZIP压缩等不支持文件分割操作的压缩方式,压缩文件只会被一个任务所读取。
    • 解决方法:数据压缩时采用bzip2和Zip等支持文件分割的压缩算法
  • 聚合计算时无法聚合中间结果

    • 如使用了collect_list聚合函数,开启hive.groupby.skewindata也没用(第一个作业均分map数据,预聚合;)
    • collect_list这类要求全量操作所有数据的中间结果来说,起不到作用
    • 解决方法:调整reduce所执行的内存大小,使用mapreduce.reduce.memory.mb
  • 两表进行Join,含有大量相同的倾斜数据键

    • 解决方法:第一个作业处理没有倾斜的数据;第二个作业将倾斜的数据存到分布式缓存中,分发到各个Map任务所在节点。在Map阶段完成join,也就是Mapjoin
  • 完成的任务 --> Reduce任务列 --> Task --> 框架计数器

  • 可以查看耗时短、耗时长、平均耗时 可判断是否存在数据倾斜

缓慢的Shuffle

  • 涉及磁盘的读写和网络传输,容易产生性能瓶颈
  • JobHistory --> JobID --> Reduce --> Elapsed Time Shuffle

特殊语句

左半连接 :left semi join

mapjoin 适用小表和大表 : map-side join

两个都是桶表 且 存在桶数倍数关系 : bucketed map join

两个都是桶表 且 存在桶数倍数关系 且 基于有序数据合并: bucketed sorted merge join

倾斜连接: skew join

获取表大部分信息 : show table extended like 表名

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值