Hive 知识整理--二

1.Hive执行流程

hiveSQL转换成MapReduce的执行计划包括如下几个步骤(6个): HiveSQL ->AST(抽象语法树) -> QB(查询块) ->OperatorTree(操作树)->优化后的操作树->mapreduce任务树->优化后的mapreduce任务树
1.Antlr定义SQL的语法规则,完成SQL词法,语法解析,将SQL转化为抽象语法树AST Tree
2.遍历AST Tree, 抽象出查询的基本组成单元QueryBlock。
3.遍历QueryBlock,翻译为执行操作树OperatorTree
4.逻辑层优化器进行OperatorTree变换,合并不必要的ReduceSinkOperator,减少shuffle数据量
5.遍历OperatorTree,翻译为MapReduce任务
6.物理层优化器进行MapReduce任务的变换,生成最终的执行计划
详细讲解

如果Join的两张表一张表是临时表,就会生成一个ConditionalTask,在运行期间判断是否使用MapJoin
CommonJoinResolver优化器
CommonJoinResolver优化器就是将CommonJoin转化为MapJoin转化过程如下:
1.深度优先遍历Task Tree
2.找到JoinOperator,判断左右表数据量大小
3.对与小表 + 大表 => MapJoinTask,对于小/大表 + 中间表 => ConditionalTask

2.Hive工作原理

在这里插入图片描述流程大致步骤为:

  1. 用户提交查询等任务给Driver。
  2. 编译器获得该用户的任务Plan。
  3. 编译器Compiler根据用户任务去MetaStore中获需要的Hive的元数据信息
  4. 编译器Compiler得到元数据信息,对任务进行编译,先将HiveQL转换为抽象语法树,然后将抽象语法树转换成查询块,将查询块转化为逻辑的查询计划(执行操作树OperatorTree),重写逻辑查询计划,将逻辑计划转化为物理的计划(MapReduce), 最后选择最佳的策略
  5. 将最终的计划提交给Driver。
    Driver将计划Plan转交给ExecutionEngine去执行,获取元数据信息,提交给JobTracker或者SourceManager执行该任务,任务会直接读取HDFS中文件进行相应的操作。
  6. 获取执行的结果。
  7. 取得并返回执行结果。
    转载自添加链接描述
    hive的架构设计可学习添加链接描述

3.HIve执行顺序

1.查询顺序:

SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ...

2.SQL的执行顺序:

FROM ... JOIN ... ON ... WHERE ... GROUP BY ... AVG SUM 等聚合函数 ... HAVING ... 计算所有表达式 ... SELECT ... DISTINCT ... ORDER BY ... LIMIT ...

3.HIVE的执行顺序:

FROM ... WHERE ... SELECT ... GROUP BY ... HAVING ... ORDER BY ...

4.Hive的执行顺序也是MapReduce的执行顺序:
map阶段:
执行from加载,进行表的查找与加载
执行where过滤,进行条件过滤与筛选
执行select查询:进行输出项的筛选
执行group by分组:描述了分组后需要计算的函数
map端文件合并:map端本地溢出写文件的合并操作,每个map最终形成一个临时文件。 然后按列映射到对应的reduceReduce阶段:
reduce阶段:
group by:对map端发送过来的数据进行分组并进行计算。
select:最后过滤列用于输出结果
limit排序后进行结果输出到HDFS文件
转载自添加链接描述
5.提升hive速度的方式
原则一:分区一定要加
原则二:连接表时使用相同的关键词,这样只会产生一个job。
原则三:减少每个阶段的数据量只选出需要的,在join表前就进行过滤
原则四:map端聚合。在上data mining的时候,写map reduce程序,有时候会在mapper和reducer之间加一个combinator,提前进行合并以减少通信成本。
hive.map.aggr=true; // 用于设定是否在 map 端进行聚合,默认值为真hive.groupby.mapaggr.checkinterval=100000; // 用于设定 map 端进行聚合操作的条目数
原则五:大表放后面。在执行多个表时,会先将前面的表放到缓存,因此最好将大表放到最后。
转载自:添加链接描述

4.Hive和传统数据库的比较

(1)Hive是什么
基于Hadoop的开源数据仓库工具,用于存储和处理海量结构化数据
Hive把HDFS中结构化的数据映射成表
Hive通过把HiveSQL进行解析和转换,最终生成一系列基于hadoop的map/reduce任务,通过执行这些任务完成数据处理
(2)HiveSQL与传统SQL的比较(9个)
查询语言不同:HiveSQL是HQL语言,传统SQL是SQL语句;
数据存储位置不同:HiveSQL是把数据存储在HDFS上,而传统SQL数据是存储在块设备或者本地文件;
数据格式:HiveSQL数据格式可以用户自定义,传统SQL有自己的系统定义格式(不同的数据库有不同的存储引擎);如: 年龄字段age在Hive中可以定义为INT,STRING,DOUBLE,定义什么型都可以,即使为STRING也可以做运算(加减乘除),在SQL只能存为数值型,STRING型排序规则是按照第一个字符进行排序
数据更新:hive不支持数据记录更新,只可以读,不可以写,而sql支持数据更新;如: 只改某一条数据的某个字段值, 在Hive中是不可以的, 只能将整个表重新导入更新
索引hive没有索引,因此查询数据的时候是通过mapreduce很暴力的把数据都查询一遍,也造成了hive查询数据速度很慢的原因,而mysql有索引;
延迟性:hive延迟性高,原因就是上边一点所说的,而mysql延迟性低;
数据规模:hive存储的数据量超级大,而mysql只是存储一些少量的业务数据;
底层执行原理:hive底层是用的mapreduce(启动需要时间准备),而mysql是excutor执行器;
可扩展性:HiveSQL高而传统SQL较低
(3).Hive的优势
把海量数据存储于 hadoop 文件系统,而不是数据库,但提供了一套类数据库的数据存储和处理机制,并采用 HQL (类 SQL )语言对这些数据进行自动化处理
不仅提供了一个熟悉SQL的用户所能熟悉的编程模型,还消除了大量的通用代码,甚至那些有时是 不得不使用Java编写的令人棘手的代码
学习成本低,可以通过类SQL语句快速实现简单的MapReduce统计,不必开发专门的MapReduce 应用,十分适合数据仓库的统计分析应用开发灵活而高效
参考:添加链接描述

5.hivesql的map join

1,什么是MapJoin?
MapJoin顾名思义,就是在Map阶段进行表之间的连接。而不需要进入到Reduce阶段才进行连接。这样就节省了在Shuffle阶段时要进行的大量数据传输。从而起到了优化作业的作用。
2,MapJoin的原理
通常情况下,要连接的各个表里面的数据会分布在不同的Map中进行处理。即同一个Key对应的Value可能存在不同的Map中。这样就必须等到Reduce中去连接。
要使MapJoin能够顺利进行,那就必须满足这样的条件除了一份表的数据分布在不同的Map中外其他连接的表的数据必须在每个Map中有完整的拷贝
3,MapJoin适用的场景
通过上面分析你会发现,并不是所有的场景都适合用MapJoin. 它通常会用在如下的一些情景:在两个要连接的表中,有一个很大,有一个很小,这个小表可以存放在内存中而不影响性能
这样我们就把小表文件复制到每一个Map任务的本地,再让Map把文件读到内存中待用。
4,MapJoin的实现方法
1)在Map-Reduce的驱动程序中使用静态方法DistributedCache.addCacheFile()增加要拷贝的小表文件,。JobTracker在作业启动之前会获取这个URI列表,并将相应的文件拷贝到各个TaskTracker的本地磁盘上。
2)在Map类的setup方法中使用DistributedCache.getLocalCacheFiles()方法获取文件目录,并使用标准的文件读写API读取相应的文件。
5,Hive内置提供的优化机制之一就包括MapJoin。
参考

  1. MapJoin简单说就是在Map阶段将小表读入内存,顺序扫描大表完成Join

上图是Hive MapJoin的原理图,从图中可以看出MapJoin分为两个阶段:
1.通过MapReduce Local Task,将小表读入内存,生成HashTableFiles上传至Distributed Cache中,这里会对HashTableFiles进行压缩。
2.MapReduce Job在Map阶段,每个Mapper从Distributed Cache读取HashTableFiles到内存中,顺序扫描大表,在Map阶段直接进行Join,将数据传递给下一个MapReduce任务。
6. 如果Join的两张表一张表是临时表,就会生成一个ConditionalTask,在运行期间判断是否使用MapJoin
CommonJoinResolver优化器
CommonJoinResolver优化器就是将CommonJoin转化为MapJoin,转化过程如下:

  • 深度优先遍历Task Tree
  • 找到JoinOperator,判断左右表数据量大小
  • 对与小表 + 大表 => MapJoinTask,对于小/大表 + 中间表 => ConditionalTask
  • 遍历上一个阶段生成的MapReduce任务,发现MapReduceTask[Stage-2] JOIN[8]中有一张表为临时表,先对Stage-2进行深度拷贝(由于需要保留原始执行计划为Backup Plan,所以这里将执行计划拷贝了一份),生成一个MapJoinOperator替代JoinOperator,然后生成一个MapReduceLocalWork读取小表生成HashTableFiles上传至DistributedCache中。
    参考:https://tech.meituan.com/2014/02/12/hive-sql-to-mapreduce.html

6.Hive HDFS HBase区别

1.定义
Hive基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射一张数据库表,并提供简单的sql查询功能,可以将sql语句转换为MapReduce任务进行运行
HBaseHadoop的数据库,一个分布式、可扩展、大数据的存储。
2.两者的特点
Hive帮助熟悉SQL的人运行MapReduce任务。因为它是JDBC兼容的,同时,它也能够和现存的SQL工具整合在一起。运行Hive查询会花费很长时间,因为它会默认遍历表中所有的数据。虽然有这样的缺点,一次遍历的数据量可以通过Hive的分区机制来控制。分区允许在数据集上运行过滤查询,这些数据集存储在不同的文件夹内,查询的时候只遍历指定文件夹(分区)中的数据。这种机制可以用来,例如,只处理在某一个时间范围内的文件,只要这些文件名中包括了时间格式。
HBase通过存储key/value来工作。它支持四种主要的操作:增加或者更新行查看一个范围内的cell获取指定的行删除指定的行、列或者是列的版本。版本信息用来获取历史数据(每一行的历史数据可以被删除,然后通过Hbase compactions就可以释放出空间)。虽然HBase包括表格,但是schema仅仅被表格和列簇所要求,列不需要schema。Hbase的表格包括增加/计数功能。
3.限制
1.Hive目前不支持更新操作。另外,由于hive在hadoop上运行批量操作,它需要花费很长的时间,通常是几分钟到几个小时才可以获取到查询的结果。Hive必须提供预先定义好的schema将文件和目录映射到列,并且Hive与ACID不兼容
2.HBase查询是通过特定的语言来编写的,这种语言需要重新学习。类SQL的功能可以通过Apache Phonenix实现,但这是以必须提供schema为代价的。另外,Hbase也并不是兼容所有的ACID特性,虽然它支持某些特性。最后但不是最重要的–为了运行Hbase,Zookeeper是必须的,zookeeper是一个用来进行分布式协调的服务,这些服务包括配置服务,维护元信息和命名空间服务
4.应用场景
1.Hive适合用来对一段时间内的数据进行分析查询,例如,用来计算趋势或者网站的日志。Hive不应该用来进行实时的查询。因为它需要很长时间才可以返回结果。
2.Hbase非常适合用来进行大数据的实时查询。Facebook用Hbase进行消息和实时的分析。它也可以用来统计Facebook的连接数。
5.总结
Hive和Hbase是两种基于Hadoop的不同技术–
Hive是一种类SQL的引擎,并且运行MapReduce任务;用来进行统计查询
Hbase是一种在Hadoop之上的NoSQL 的Key/vale数据库,用来进行实时查询
这两种工具是可以同时使用的。就像用Google来搜索,用FaceBook进行社交一样;,数据也可以从Hive写到Hbase,设置再从Hbase写回Hive
转载自

7.维度和度量

简单记:维度是环境,度量是指标或者是衡量
1.维度:即观察数据的角度.比如员工数据,可以从性别角度来分析,也可以更加细化,从入职时间或者地区的维度来观察.
维度是一组离散的值,比如说性别中的男和女,或者时间维度上的每一个独立的日期.
因此在统计时可以将维度值相同的记录聚合在一起,然后应用聚合函数做累加/平均/最大和最小值等聚合计算.
2.度量:即被聚合(观察)的统计值,也就是聚合运算的结果.比如说员工数据中不同性别员工的人数,又或者说在同一年入职的员工有多少.
详细介绍

8.hivesql优化问题

添加链接描述

9.Hive的UDF是什么?

1.UDF的全称为user-defined function,用户定义函数
为什么有它的存在呢?有的时候 你要写的查询无法轻松地使用Hive提供的内置函数来表示,通过写UDF,Hive就可以方便地插入用户写的处理代码并在查询中使用它们,相当于在HQL(Hive SQL)中自定义一些函数。
2.首先UDF必须用java语言编写,Hive本身就是用java写的。所以想学好hadoop这个分布式框架的相关技术,熟练使用java就是基本功了!
3.Hive中有三种UDF:(普通)UDF、用户定义聚集函数(user-defined aggregate function,UDAF)、用户定义表生成函数(user-defined table-generating function,UDTF)
UDF操作作用于单个数据行,并且产生一个数据行作为输出。大多数函数都属于这一类(比如数学函数和字符串函数)。
UDAF 接受多个输入数据行,并产生一个输出数据行。想COUNT和MAX这样的函数就是聚集函数。
UDTF 操作作用于单个数据行,并且产生多个数据行-------一个表作为输出,如lateral view explode()函数
Q:字节面试题,为什么UDTF应用的不多?
答:因为UDAF+现有的UDTF函数(如lateral view explode())能满足现有需求
4.首先一个UDF必须满足下面两个条件:
1 一个UDF必须是org.apache.hadoop.hive.ql.exec.UDF的子类(换句话说就是我们一般都是去继承这个类)
2 一个UDF必须至少实现了evaluate()方法
注意UDF名不是大小写敏感的
5.一个UDAF计算函数必须实现下面的5个方法:
1 init()方法
init()方法负责初始化计算函数并重设它的内部状态。在MaximumIntUDAFEvaluator中,我们把存放最终结果的IntWritable对象设置为null。我们使用null来表示目前还没有对任何值进行聚集计算,这和对空集NULL计算最大值应有的结果是一致的。
**2 iterate()方法 **
每次对一个新值进行聚集计算时都会调用iterate()方法。计算函数要根据聚集计算的结果更新其内部状态。iterate()接受的参数和Hive中被调用函数的参数使对应的。
**3 terminatePartial()方法 **
Hive需要部分聚集结果时会调用terminatePartial()方法。这个方法必须返回一个封装了聚集计算当前状态的对象。
4 merge()方法
在Hive决定要合并一个部分聚集值和另一个部分聚集值时会调用merge()方法。该方法接受一个对象作为输入。这个对象的类型必须和terminatePartial()方法返回的类型一致。
5 terminate()
Hive需要最终聚集结果时会调用terminate()方法。计算函数需要把状态作为一个值返回。
转载自:添加链接描述

10.hive的map/reduce数怎么确定?

转载自:https://blog.csdn.net/zhong_han_jun/article/details/50814246

10.1 先说结论:

由于mapreduce中没有办法直接控制map数量,所以只能曲线救国,通过设置每个map中处理的数据量进行设置reduce是可以直接设置的
控制map和reduce的参数

set mapred.max.split.size=256000000;        -- 决定每个map处理的最大的文件大小,单位为B
set mapred.min.split.size.per.node=1;         -- 节点中可以处理的最小的文件大小
set mapred.min.split.size.per.rack=1;         -- 机架中可以处理的最小的文件大小
# 注意各参数的设置大小,不要冲突,否则会异常,大小顺序如下
mapred.max.split.size <= mapred.min.split.size.per.node <= mapred.min.split.size.per.rack
方法1
set mapred.reduce.tasks=10;  -- 设置reduce的数量
方法2
set hive.exec.reducers.bytes.per.reducer=1073741824 -- 每个reduce处理的数据量,默认1GB

补充说明:一个集群可以有多个机架一个机架有1至多个节点,这里的集群是mapreduce不是yarn,yarn没有详细了解过,另外如果想要实现map中的数据合并需要设置下面的参数,集群默认就是这个格式

set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

需要确认的问题:
 a.我们该设置多少个map多少个reduce才合适?
  map数普遍是通过执行时长来确认的至少应当保证每个map执行时长在1分钟以上太短的话意味着大量重复的jvm启用和销毁。具体设置要根据具体任务来处理,有些任务占用cpu大,有些占用io大。
  我这边的话因为大任务经常搞了上千个map,作为小集群影响还是蛮大的,所以只对监控到的hql产生过大的map和reduce进行调整,经过一些简单测试,map数保证在三四百个其实不影响执行效率。
 b.设置了上面的参数会带来什么影响?
  设置map的话,影响不是很大,可能会带来更多的集群之间的io,毕竟要做节点之间的文件合并
  设置reduce的话,如果使用mapred.reduce.tasks,这个影响就大了,至少会造成同一个session每一个mr的job的reduce都是这么多个,而且reduce个数意味着最后的文件数量的输出,如果小文件太多的话可以打开reduce端的小文件合并参数,set hive.merge.mapredfiles=true

10.2 控制map数量的三个参数的逻辑概念

可以简单的理解为集群对一个表分区下面的文件进行分发到各个节点,之后根据mapred.max.split.size确认要启动多少个map数,逻辑如下
  a.假设有两个文件大小分别为(256M,280M)被分配到节点A,那么会启动两个map,剩余的文件大小为10MB和35MB因为每个大小都不足241MB会先做保留
  b.根据参数set mapred.min.split.size.per.node看剩余的大小情况并进行合并,如果值为1,表示a中每个剩余文件都会自己起一个map,这里会起两个,如果设置为大于4510241024则会合并成一个块,并产生一个map
  如果mapred.min.split.size.per.node为1010241024,那么在这个节点上一共会有4个map,处理的大小为(245MB,245MB,10MB,10MB,10MB,10MB),余下9MB
  如果mapred.min.split.size.per.node为4510241024,那么会有三个map,处理的大小为(245MB,245MB,45MB)
  实际中mapred.min.split.size.per.node无法准确地设置成4510241024,会有剩余并保留带下一步进行判断处理
  c. 对b中余出来的文件与其它节点余出来的文件根据mapred.min.split.size.per.rack大小进行判断是否合并,对再次余出来的文件独自产生一个map处理

10.3 控制map数量的简单实用方式

我们执行一个hive语句,发现起了1000个map,这种情况对于当前的数据量来说是完全不必要的,同时还会影响其它用户提交任务
这个时候希望map减小到250个左右,很简单
map处理的最大的文件大小增大,256000000*4=1024000000
参数修改为如下

set mapred.max.split.size=1024000000;
set mapred.min.split.size.per.node=1024000000;
set mapred.min.split.size.per.rack=1024000000;

改参数之后,如下图,可以看到map数量减少到370,至于为什么单个map处理的数据量增大了map数却不是按倍数减少到1185/4=296个,原因在文件合并过程中对于如何起map数并不是单纯的看总的文件大小存在一些更优化的算法,如考虑带宽、IO、当前map分配等

10.4 控制reduce参数

修改reduce的个数就简单很多,直接根据可能的情况作个简单的判断确认需要的reduce数量,如果无法判断,根据当前map数减小10倍,保持在1~100个reduce即可(注意,这个不同的集群需求不同哈)
设置参数如下

set mapred.reduce.tasks=10
不建议随意设置reduce参数哈,可能调整参数更好一点
set hive.exec.reducers.bytes.per.reducer=1073741824

10.5 控制map和rduce数的说明

1、因为set参数的设置是session级别的,Toad for Cloud(青蛙)第三方软件中暂时没有发现如何使set的参数设置有效的,所以请使用CRT等工具连接到linux的界面中进行使用,使用hive命令连接hive集群,一次设置只要不结束这次连接,那么参数是始终有效的。
  2、注意各参数的设置大小,不要冲突,否则会异常,大小顺序如下
mapred.max.split.size <= mapred.min.split.size.per.node <= mapred.min.split.size.per.rack
  3、这种减少map数的行为是否能带来更短的执行时间,需要具体分析,map数也不是越少越好,减少了map数,单个map处理的数据量就上升,需要更多的时间,同时也因为需要合并节点内、节点间甚至机架之间的数据需要更多的IO和带宽
  参数的设置本质是根据文件情况、系统情况、数据计算情况进行的一个平衡考虑,有取有舍,我们需要遵循的规则就是:使大数据量利用合适的map数;使单个map任务处理合适的数据量
  4、reduce数同3

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值