一文弄懂Hive基本架构和原理——Hive元数据信息存储在Hive MetaStore中,Hive 中所有的数据都存储在 HDFS 中,Hive 中数据模型:Table,External Table,Partition,Bucket;最后将一个SQL变成hadoop MapReduce作业

一文弄懂Hive基本架构和原理
from:https://blog.csdn.net/oTengYue/article/details/91129850

文章目录

    概述
    Hive架构
    Hive数据模型
    Hive SQL的编译
    Hive执行计划
    Hive Sql的MapReduce实现原理
        Join的实现原理
        Group By的实现原理
        Distinct的实现原理
    Hive文件压缩和文件存储
        Hive建表指定文件格式
        Hive建表指定压缩
        Hive动态设置压缩
            Hive中间数据压缩
            Hive最终数据压缩
    Hive Map和Reduce数量计算
        Map数量
        Reduce数量
    数据倾斜
        Group by引起的数据倾斜
        Join引起的数据倾斜
            Skew join
            重写业务逻辑
    Hive性能优化
    常见问题
        请说明hive中 Sort By,Order By,Cluster By,Distrbute By各代表什么意思
        NULL在hive的一般处理
        multi-group新特性的好处?
    参考

概述

Hive是建立在 Hadoop 上的数据仓库基础构架。

它提供了一系列的工具,可以用来进行数据提取转化加载(ETL),这是一种可以存储、查询和分析存储在 Hadoop 中的大规模数据的机制。

Hive 定义了简单的类 SQL 查询语言,称为 HQL,它允许熟悉 SQL 的用户查询数据。同时,这个语言也允许熟悉 MapReduce 开发者的开发自定义的 mapper 和 reducer 来处理内建的 mapper 和 reducer 无法完成的复杂的分析工作。

可以将SQL 查询转换为MapReduce 的job 在Hadoop集群上执行。

官方文档:https://cwiki.apache.org/confluence/display/Hive/Home
Hive架构

在这里插入图片描述
从架构图上可以很清楚地看出Hive和Hadoop(MapReduce,HDFS)的关系。

    Hive是最上层,即客户端层或者作业提交层。
    MapReduce/Yarn是中间层,也就是计算层。
    HDFS是底层,也就是存储层。

facebook的一张架构图
在这里插入图片描述
从Facebook的图上可以看出,Hive主要有QL,MetaStore和Serde三大核心组件构成。QL就是编译器,也是Hive中最核心的部分。Serde就是Serializer和Deserializer的缩写,用于序列化和反序列化数据,即读写数据。MetaStore对外暴露Thrift API,用于元数据的修改。比如表的增删改查,分区的增删改查,表的属性的修改,分区的属性的修改等。
Hive数据模型

在这里插入图片描述

Hive元数据信息存储在Hive MetaStore中,如文件路径、文件格式、列、数据类型、分隔符,Hive默认的分格符有三种,分别是A(Ctrl+A)、B和^C,即ASCii码的1、2和3,分别用于分隔列,分隔列中的数组元素,和元素Key-Value对中的Key和Value。
Hive 中所有的数据都存储在 HDFS 中,Hive 中包含以下数据模型:Table,External Table,Partition,Bucket。
(1)表table:一个表就是hdfs中的一个目录
(2)区Partition:表内的一个区就是表的目录下的一个子目录
(3)桶Bucket:如果有分区,那么桶就是区下的一个单位,如果表内没有区,那么桶直接就是表下的单位,桶一般是文件的形式。
Hive SQL的编译

一条SQL,进入的Hive。经过上述的过程,其实也是一个比较典型的编译过程变成了一个作业。
在这里插入图片描述
Hive是如何将SQL转化为MapReduce任务的,整个编译过程分为六个阶段:

(1)Antlr定义SQL的语法规则,完成SQL词法,语法解析,将SQL转化为抽象语法树AST Tree

(2)遍历AST Tree,抽象出查询的基本组成单元QueryBlock

(3)遍历QueryBlock,翻译为执行操作树OperatorTree

(4)逻辑层优化器进行OperatorTree变换,合并不必要的ReduceSinkOperator,减少shuffle数据量

(5)遍历OperatorTree,翻译为MapReduce任务

(6)物理层优化器进行MapReduce任务的变换,生成最终的执行计划
Hive执行计划

可以通过查看Explain查看一个一个SQL如何变成MapReduce作业的过程的过程,例如在hive cli中执行:explain sql语句就能看到

官网LanguageManual Explain:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Explain#LanguageManualExplain-TheASTClause
在这里插入图片描述
下面是执行的一个例子:
Xnip2019-06-06_14-08-13
Hive Sql的MapReduce实现原理

hive把复杂sql分解成多个MapReduce chain执行,各MR的中间结果存在为hdfs的临时文件,然后链式跑完即可获得最终结果。因此,只需明白其核心即可见微知著,下面介绍join、group by和distinct原理(直接摘抄美团技术团队的总结,so 感谢):
Join的实现原理

select u.name, o.orderid from order o join user u on o.uid = u.uid;
在map的输出value中为不同表的数据打上tag标记,在reduce阶段根据tag判断数据来源。MapReduce的过程如下(这里只是说明最基本的Join的实现,还有其他的实现方式)
在这里插入图片描述
Group By的实现原理

select rank, isonline, count(*) from city group by rank, isonline;
将GroupBy的字段组合为map的输出key值,利用MapReduce的排序,在reduce阶段保存LastKey区分不同的key。MapReduce的过程如下(当然这里只是说明Reduce端的非Hash聚合过程)
在这里插入图片描述
Distinct的实现原理

select dealid, count(distinct uid) num from order group by dealid;
当只有一个distinct字段时,如果不考虑Map阶段的Hash GroupBy,只需要将GroupBy字段和Distinct字段组合为map输出key,利用mapreduce的排序,同时将GroupBy字段作为reduce的key,在reduce阶段保存LastKey即可完成去重
在这里插入图片描述
Hive文件压缩和文件存储

hive对文件的压缩是对内容的压缩,也就是说对文件的压缩不是先生成文件,再对文件压缩,而是在生成文件时,对其中的内容字段进行压缩,最终压缩后,对外仍体现为某种具体的压缩文件。

常用的压缩编解码器如下表:
在这里插入图片描述

常用的文件格式:
(1) Textfile

    文本格式,Hive的默认格式,数据不压缩,磁盘开销大、数据解析开销大。可结合Gzip、Bzip2使用,但使用Gzip这种方式,hive不会对数据进行切分,从而无法对数据进行并行操作。行式存储
    对应的hive API为:org.apache.hadoop.mapred.TextInputFormat和org.apache.hive.ql.io.HiveIgnoreKeyTextOutputFormat

(2)SequenceFile

    Hadoop提供的一种二进制文件格式是Hadoop支持的标准文件格式(其他生态系统并不适用),可以直接将对序列化到文件中,所以sequencefile文件不能直接查看,可以通过Hadoop fs -text查看。具有使用方便,可分割,可压缩,可进行切片。压缩支持NONE, RECORD, BLOCK(优先)等格式,可进行切片。行式存储
    对应hive API为:org.apache.hadoop.mapred.SequenceFileInputFormat和org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat

(3)RCFile

    是一种行列存储相结合的存储方式,先将数据按行进行分块再按列式存储,保证同一条记录在一个块上,避免读取多个块,有利于数据压缩和快速进行列存储。列式存储
    对应的hive API为:org.apache.hadoop.hive.ql.io.RCFileInputFormat和org.apache.hadoop.hive.ql.io.RCFileOutputFormat

(4)ORCFile

    orcfile是对rcfile的优化,可以提高hive的读写、数据处理性能,提供更高的压缩效率(目前主流选择之一)。列式存储

(5)Parquet

    一种列格式, 可提供对其他 hadoop 工具的可移植性, 包括Hive, Drill, Impala, Crunch, and Pig
    对应的hive API为:org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat和org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat

(6)Avro

    Avro是一个数据序列化系统,设计用于支持大批量数据交换的应用。它的主要特点有:支持二进制序列化方式,可以便捷,快速地处理大量数据;动态语言友好,Avro提供的机制使动态语言可以方便地处理Avro数据。
    对应的hive API为:org.apache.hadoop.hive.ql.io.avro.AvroContainerInputFormat和org.apache.hadoop.hive.ql.io.avro.AvroContainerOutputFormat

几种文件存储格式的性能测试结果:
存储格式     ORC     Sequencefile     Parquet     RCfile     Avro
数据压缩后大小     1.8G     67.0G     11G     63.8G     66.7G
存储耗费时间     535.7s     625.8s     537.3s     543.48     544.3
SQL查询响应速度     19.63s     184.07s     24.22s     88.5s     281.65s

实践中常用的压缩+存储可以选择(部分)
Textfile+Gzip
SequenceFile+Snappy
ORC+Snappy
Hive建表指定文件格式

[STORED AS file_format]
file_format:
  : SEQUENCEFILE
  | TEXTFILE -- (Default, depending on hive.default.fileformat configuration)
  | RCFILE -- (Note: Available in Hive 0.6.0 and later)
  | ORC -- (Note: Available in Hive 0.11.0 and later)
  | PARQUET -- (Note: Available in Hive 0.13.0 and later)
  | AVRO -- (Note: Available in Hive 0.14.0 and later)
  | JSONFILE -- (Note: Available in Hive 4.0.0 and later)
  | INPUTFORMAT input_format_classname OUTPUTFORMAT output_format_classname

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

注:
Hive wiki CreateTable:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-CreateTable
Hive建表指定压缩

CREATE EXTERNAL TABLE IF NOT EXISTS tb_test(
     id bigint COMMENT 'id',
     name string COMMENT 'name'      
 )
COMMENT 'test table'
PARTITIONED BY (dt string)
STORED AS ORC
tblproperties ('orc.compress'='SNAPPY');

    1
    2
    3
    4
    5
    6
    7
    8

Hive动态设置压缩
压缩格式     Hadoop压缩编码/解码器
Deflate     org.apache.hadoop.io.compress.DeflateCodec
gzip     org.apache.hadoop.io.compress.GzipCodec
bzip2     org.apache.hadoop.io.compress.BZip2Codec
LZO     com.hadoop.compression.lzo.LzopCodec
Lz4     org.apache.hadoop.io.compress.Lz4Codec
Snappy     org.apache.hadoop.io.compress.SnappyCodec
Hive中间数据压缩

hive.exec.compress.intermediate:默认该值为false,设置为true为激活中间数据压缩功能。就是在MapReduce的shuffle阶段对mapper产生的中间结果数据压缩。在这个阶段,优先选择一个低CPU开销的算法。

set hive.exec.compress.intermediate=true;
set mapred.map.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec;

    1
    2

Hive最终数据压缩

hive.exec.compress.output:用户可以对最终生成的Hive表的数据通常也需要压缩。该参数控制这一功能的激活与禁用,设置为true来声明将结果文件进行压缩。

set hive.exec.compress.output=true;
set mapred.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec;

    1
    2

参考:
Hive支持的文件格式与压缩算法:https://my.oschina.net/hulubo/blog/915072?tdsourcetag=s_pctim_aiomsg(推荐)
File Formats:https://cwiki.apache.org/confluence/display/Hive/FileFormats
Hive文件存储格式:https://www.jianshu.com/p/694f044d1c34
Hive压缩格式:https://www.cnblogs.com/skyl/p/4740301.html
如何在MapReduce中使用SequenceFile数据格式?http://blog.itpub.net/31077337/viewspace-2214505
如何在MapReduce中使用Avro数据格式?http://blog.itpub.net/31077337/viewspace-2214709
Hive Map和Reduce数量计算
Map数量


num_Map_tasks = max[${Mapred.min.split.size},
                min(${dfs.block.size}, ${Mapred.max.split.size})]

    1
    2
    3

    Mapred.min.split.size指的是数据的最小分割单元大小。
    Mapred.max.split.size指的是数据的最大分割单元大小。
    dfs.block.size指的是HDFS设置的数据块大小。

一般来说dfs.block.size这个值是一个已经指定好的值,而且这个参数Hive是识别不到的,所以实际上只有Mapred.min.split.size和Mapred.max.split.size这两个参数(本节内容后面就以min和max指代这两个参数)来决定Map数量。在Hive中min的默认值是1B,max的默认值是256MB。所以如果不做修改的话,就是1个map task处理256MB数据,我们就以调整max为主。通过调整max可以起到调整Map数的作用,减小max可以增加Map数,增大max可以减少Map数 。需要提醒的是,直接调整Mapred.Map.tasks这个参数是没有效果的。
Reduce数量

这里说的Reduce阶段,是指前面流程图中的Reduce phase(实际的Reduce计算)而非图中整个Reduce task。Reduce阶段优化的主要工作也是选择合适的Reducetask数量,跟上面的Map优化类似。
与Map优化不同的是,Reduce优化时,可以直接设置Mapred。Reduce。tasks参数从而直接指定Reduce的个数。当然直接指定Reduce个数虽然比较方便,但是不利于自动扩展。Reduce数的设置虽然相较Map更灵活,但是也可以像Map一样设定一个自动生成规则,这样运行定时Job的时候就不用担心原来设置的固定Reduce数会由于数据量的变化而不合适。

Hive估算Reduce数量的时候,使用的是下面的公式:

num_Reduce_tasks = min[${Hive.exec.Reducers.max},
                      (${input.size} / ${ Hive.exec.Reducers.bytes.per.Reducer})]

    1
    2

也就是说,根据输入的数据量大小来决定Reduce的个数,默认Hive.exec.Reducers.bytes.per.Reducer为1G,而且Reduce个数不能超过一个上限参数值,这个参数的默认取值为999。所以我们可以调整Hive.exec.Reducers.bytes.per.Reducer来设置Reduce个数。
数据倾斜

定义: 由于数据分布不均匀,造成数据热点。

现象: 一个或几个key的记录数与平均记录数差异过大,最长时长远大于平均时长。任务进度长时间维持在99%(或100%),查看任务监控页面,发现只有少量(1个或几个)reduce子任务未完成。

数据倾斜优化:一般分为join引起和group by引起分别解决。
操作     原因     现象
Group by     分组key集中     处理某key值的reduce非常耗时
Join     关联key集中(例如关联字段空值过多)     处理某key值的reduce非常耗时
Group by引起的数据倾斜

分两方面优化:
第一个:
set hive.map.aggr=true;
set hive.groupby.mapaggr.checkinterval=100000;
set hive.map.aggr.hash.min.reduction=0.5;
hive.map.aggr=true(默认)参数控制在group by的时候是否map局部聚合,但也不是都会局部聚合,如果聚合前后差别不是很大,聚合也就没什么意义了。
后两个设置是判断是否需要做map局部聚合,即:预先取100000条数据聚合,如果聚合后的条数/100000>0.5,则不再聚合。

第二个:
set Hive.groupby.skewindata=true;
控制启动两个MR Job完成,第一个Job先不按GroupBy字段分发,而是随机分发做一次聚合,然后启动第二个Job,拿前面聚合过的数据按GroupBy字段分发计算出最终结果。但是否生效还存在限制,详情见 Hive-hive.groupby.skewindata配置相关问题调研
Join引起的数据倾斜

优化主要分两个方向:skew join和重写业务逻辑
Skew join

set hive.optimize.skewjoin=true;
set hive.skewjoin.key=100000;
记录超过hive.skewjoin.key(默认100000)阈值的key值先写入hdfs,然后再进行一个map join的job任务,最终和其他key值的结果合并为最终结果。其过程如下图:
在这里插入图片描述
重写业务逻辑

这个需要结合具体的场景重写,例如:在日志表与用户表关联时候(通过user_id关联),直接关联可能导致user_id为null的发生数据倾斜,此时可以把日志表中user_id为null的单独处理,如下:

SELECT a.xx, b.yy FROM log a JOIN users b
            ON a.user_id IS NOT NULL
                AND a.user_id = b.user_id
UNION ALL
SELECT a.xx, NULL AS yy FROM log a WHERE a.user_id IS NULL;

    1
    2
    3
    4
    5

参考:
HiveQL中如何排查数据倾斜问题:https://blog.csdn.net/u012151684/article/details/77074356
Hive性能优化

见另一篇博文 Hive常用优化参数
常见问题
请说明hive中 Sort By,Order By,Cluster By,Distrbute By各代表什么意思

    order by:会对输入做全局排序,因此只有一个reducer(多个reducer无法保证全局有序)。只有一个reducer,会导致当输入规模较大时,需要较长的计算时间。

    sort by:对分区内的数据进行排序,不是全局排序,其在数据进入reducer前完成排序。

    distribute by:对map输出进行分区,按照指定的字段对数据进行划分输出到不同的reduce中。常和sort by一起使用,例如:select mid, money, name from store distribute by mid sort by mid asc, money asc

    cluster by:当 distribute by 和 sorts by 字段相同时,可使用 cluster by 方式替代,cluster by 具有 distribute by 和 sort by 的组合功能。但是排序只能是升序排序,不能指定排序规则为ASC或者DESC

NULL在hive的一般处理

NULL默认的存储都是\N,可以在建表时通过serialization.null.format的设置。
NULL 值的过滤,一般是is null 和 is not null。
multi-group新特性的好处?

multi group by 可以将查询中的多个group by操作组装到一个MapReduce任务中,起到优化作用。例如:


from area
    insert overwrite table temp1
        select Provice,city,county,count(rainfall) from area where data="2018-09-02" group by provice,city,count
    insert overwrite table temp2
        select Provice,count(rainfall) from area where data="2018-09-02" group by provice

参考

官方文档:https://cwiki.apache.org/confluence/display/Hive/Home
HiveSQL的编译过程(美团):https://tech.meituan.com/2014/02/12/hive-sql-to-mapreduce.html
HiveSQL编译过程: https://www.slideshare.net/recruitcojp/internal-hive
Hive的核心原理以及查询优化:http://www.pianshen.com/article/4247149029
深入浅出数据仓库中SQL性能优化之Hive篇:http://www.codeceo.com/article/sql-hive.html
————————————————
版权声明:本文为CSDN博主「HaiwiSong」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/oTengYue/article/details/91129850

猜你喜欢

转载自www.cnblogs.com/bonelee/p/12441622.html