HIVE MR知识巩固

概念

Hive 将 HQL 转换成MapReduce 执行 ,可以说Hive 是基于 hadoop的一个数据仓库工具,实质就是一款基于 HDFS的 MapReduce 计算框架

我的大白话解释

其实Hive就是基于hdfs以及mr的数据仓库,通过hql进行数据的导入,以及对数据的离线分析。导入数据是将结构化的数据文件映射为一张数据库表,离线分析则是将hql翻译为mr进行执行。

相关组件

Metastore :存储系统目录以及关于表、列、分区等元数据的组件

Driver:该组件包括Complier、Optimizer和Executor,它的作用是将我们写的HiveQL(类SQL)语句进行解析、编译优化,生成执行计划,然后调用底层的mapreduce计算框架。

Thrift服务:它用来进行可扩展且跨语言的服务的开发,hive集成了该服务,能让不同的编程语言调用hive的接口。

客户端组件:CLI:command line interface,命令行接口。
Thrift客户端: hive架构的许多客户端接口是建立在thrift客户端之上,包括JDBC和ODBC接口。
WEBGUI:hive客户端提供了一种通过网页的方式访问hive所提供的服务。这个接口对应hive的hwi组件(hive web interface),使用前要启动hwi服务。

运行机理

  1. 命令行或Web UI之类的Hive接口将查询语句发送给Driver
  2. Driver借助查询编译器解析查询语句,检查语法和查询计划或查询需求
  3. 编译器将元数据请求发送到Metastore
  4. Metastore将元数据响应给编译器
  5. 编译器检查需求并将计划重新发送给Driver。
    到目前为止,查询的解析和编译已经完成
  6. Driver将执行计划发送到执行引擎
  7. 在内部,执行任务的过程是MapReduce Job。执行引擎将Job发送到ResourceManager, ResourceManager位于Name节点中,并将job分配给datanode中的NodeManager。在这里,查询执行MapReduce任务.
  8. 执行引擎将从datanode上获取结果集
  9. 执行引擎将这些结果值发送给Driver
  10. Driver将结果发送到Hive接口

hive建表 数据导入
普通表创建 导入
创建表 导入数据字段按逗号分隔开
create table if not exists brand_dimension
(bid STRING,
category STRING,
brand STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ',‘;

导入数据 local字段为linux本地导入 不加则为hdfs目录
load data local inpath ‘/hivedata/user.data’ overwrite into table brand_dimension ;

分区表

month值一致的所有记录存放在一个分区中,分区,这是将满足某些条件的记录打包,做个记号,在查询时提高效率,相当于按文件夹对文件进行分类。
create external table if not exists stocks (
empno int,
ename string,
job string,
mgr int
)
partitioned by (month string)
row format delimited fields terminated by ‘,’

导入数据

load data local inpath ‘hivedata/stocks/NASDAQ/AAPL/stocks.csv’ overwrite into table stocks partition(month=“201812”);
insert into table stocks partition(month=‘201812’) select * from stocks 2;

外部表

指定表存放文件位置创建外部表,drop表 指挥删除元数据,不删除hdfs文件数据
reate external table if not exists stocks (
empno int,
ename string,
job string,
mgr int
)
row format delimited fields terminated by ‘,’
LOCATION ‘bigdata/stocks’;
处理json数据
{“id”:1701439105,“ids”:[2154137571,3889177061,1496915057,……,1663973284],“total_number”: 493}
select get_json_object(t.json,’.id),getjsonobject(t.json,.id'), get_json_object(t.json,'.total_number’) from tmp_json_test t ;

数据格式

1、TEXTFILE :默认格式,建表时不指定默认为这个格式,导入数据时会直接把数据文件拷贝到hdfs上不进行处理。
2、SEQUENCEFILE 一种Hadoop API提供的二进制文件,使用方便、可分割、可压缩等特点。
3:ORC:ORC是RCfile的升级版,性能有大幅度提升, 而且数据可以压缩存储,压缩比和Lzo压缩差不多,比text文件压缩比可以达到70%的空间。而且读性能非常高,可以实现高效查询。
4、RCFILE : 一种行列存储相结合的存储方式。首先,其将数据按行分块,保证同一个record在一个块上,避免读一个记录需要读取多个block。其次,块数据列式存储,有利于数据压缩和快速的列存取。理论上具有高查询效率(但hive官方说效果不明显,只有存储上能省10%的空间,所以不好用,可以不用)。

自定义函数函数
分三类
UDF 一进一出 处理原文件内容某些字段包含 [] “”
UDAF 多进一出 sum() avg() max() min()
UDTF 一进多出 ip -> 国家 省 市

UDF函数的开发
** 必须继承UDF类
** 重写evaluate函数 支持重载
** 必须要有返回类型,可以返回null,但是返回类型不能为void
使用方式
1、编程
2、把程序到出为jar包放到目标机器上去:
hive> add jar /home/beifeng/jars/lower.jar ;
3、创建临时函数:
hive> CREATE TEMPORARY FUNCTION my_lower AS ‘包名.类名’;
4**、使用指定函数**:
hive> show fuctions ;
hive> select my_lower(ename) from emp ;

MapReduce工作流程

基本流程:

1,数据经split划分成大小相等的数据块(数据块的大小一般等于HDFS一个块的大小)以及用户作业程序。
2,系统中有一个负责调度的Master节点和许多的Map工作节点,Reduce工作节点
3,用户作业程序提交给Master节点,Master节点寻找合适的Map节点,并将数据传给Map节点,并且Master也寻找合适的Reduce节点并将数据传给Reduce节点
4,Master节点启动Map节点执行程序,Map节点尽可能的读取本地或本机架上的数据块进行计算。(数据本地化是Mapreduce的核心特征)
5,每个Map节点处理读取的数据块,并做一些数据整理,并且将中间结果放在本地而非HDFS中,同时通知Master节点Map工作完成,并告知中间结果的存储位置。
6,Master节点等所有Map工作完成后,开始启动Reduce节点,Reduce节点通过Master节点掌握的中间结果的存储位置来远程读取中间结果。
7,Reduce节点将中间结果处理后将结果输出到一个文件中

MapReduce 的shuffle过程

在这里插入图片描述
MapReduce确保每个reducer的输入都是按键排序的。系统执行排序、将map输出作为输入传给reducer的过程称为Shuffle。

1 map端
map函数开始产生输出时,利用缓冲的方式写到内存并排序具体分一下几个步骤。

  1. map数据分片:把输入数据源进行分片,根据分片来决定有多少个map,每个map任务都有一个环形内存缓冲区用于存储任务输出,默认情况下缓冲区大小为100MB,可通mapreduce.task.io.sort.mb来调整。
  2. map排序:当map缓冲区大小达到阈值时(mapreduce.map.sort.spill.percent),就会将内存的数据溢写到磁盘,根据reducer的个数划分成相应的partition,在内存中按键值进行排序,如果有combiner函数,在排序后就会应用,排序后写入分区磁盘文件中。溢写的过程中,map会阻塞直到写磁盘过程完成。每次内存缓冲区到达溢出阈值,就会新建一个溢出文件件,在map写完最后一个输出记录之后,会有几个溢出文件,在任务完成之前溢出文件会被合并成一个已分区且已经排序的输出文件
    2reduce端
  3. reduce复制:每个map任务的完成时间不同,在所有任务完成时,reduce任务就开始复制其输出,这就是reduce任务的复制阶段。如果map输出很小,会被复制到reduce任务JVM的内存,否则输出被复制到磁盘。如果内存缓冲区达到阈值大小或达到map输出阈值,则合并溢出写到磁盘中,如果指定combiner,则在合并期间运行它。随着磁盘上副本增多,后台线程会将他们合并为更大的,排序的文件。
  4. reduce合并排序:这个阶段合并map输出,维持其顺序排序,这是循环进行的,如果有50个map输出,合并因子是10,合并将进行5次,最后有5个中间文件。
  5. reduce:直接把数据输入reduce函数,从而省略了一次磁盘的往返行程。

数据倾斜

产生原因

  1. key 的分化严重不均,造成一部分数据很多,一部分数据很少的局面
    2.机器性能分配不均(机器配置和数据量存在一个合理的比例)
  2. join的key值发生倾斜,key值包含很多空值或是异常值
    4.SQL语句造成数据倾斜
    group by 维度过小,某值的数量过多,处理某值的reduce非常耗时
    去重 distinct count(distinct xx),某特殊值过多,处理此特殊值的reduce耗时
    连接 join,其中一个表较小,但是key集中,分发到某一个或几个Reduce上的数据远高于平均值

解决方案

调优参数

set hive.map.aggr=true 在map中会做部分聚集操作,效率更高但需要更多的内存。
set hive.groupby.skewindata=true; 数据倾斜时负载均衡。使计算变成了两个mapreduce,先在第一个中在 shuffle 过程 partition 时随机给 key 打标记,使每个key 随机均匀分布到各个 reduce 上计算,但是这样只能完成部分计算,因为相同key没有分配到相同reduce上,所以需要第二次的mapreduce,这次就回归正常 shuffle,但是数据分布不均匀的问题在第一次mapreduce已经有了很大的改善,因此基本解决数据倾斜。

SQL语句优化

  1. 大小表进行连接时,使用map join让小表先进内存,在map端完成reduce。
  2. 大表连接大表时,如果是空值造成数据倾斜,那么把空值变成一个字符串加上随机数,把这部分倾斜的数据分发到不同的reduce上。
  3. 如果count distinct有大量相同特殊值 (如空值) 空值可以不用处理,直接最后count结果加1即可。或者空值单独拿出来处理,最后再union回去。
  4. 不同数据类型关联 默认的hash操作会按其中一种类型的值进行分配,导致别一种类型全部分发到同一个reduce中。把两个关联的类型转换成相同类型。

其他解决方案

1.增加reduce 的jvm内存(单个值有大量记录, 这种值的所有纪录已经超过了分配给reduce 的内存)
2. 增加reduce 个数(唯一值较多,单个唯一值的记录数不会超过分配给reduce 的内存)
Map join
hive 中的join可分为俩类,一种是common join(也叫Reduce join或shuffle join),另一种是 map join,后者是对hive join的一个优化,利用本地的task对较小的表hash生产一个hashtable文件,然后直接和map出来另一个表进行匹配,最终完成join
set hive.auto.convert.join = true在0.11.0到之后的版本是ture,代表使用优化

map join 没有shuffle过程,他是对小表进行hash到hdfs 临时缓存中生成hashtable file,然后直接匹配,正常的join是使用俩个map和一个reduce来完成join,因为过程中有shuffle,所以会有网络io,执行效率相对较小

https://blog.csdn.net/WYpersist/article/details/80102757?utm_source=blogxgwz3

hive行专列:https://www.cnblogs.com/kimbo/p/6208973.html

mysql行专列:
https://www.cnblogs.com/ken-jl/p/8570518.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章