大数据开发之路:hive篇

引语


大数据开发之路漫漫其修远兮,吾将上下而求索。很多入门大数据的小伙伴,可能第一个接触到的,就是一只可爱的“小象”,也就是我们的大数据领域的数据仓库工具hive。



 

 


这只小象给我们提供了方便类SQL查询语言HQL来操纵数据,使得我们一开始不用编写复杂的代码,就可以轻松的探索数据。Hive对于熟悉传统数据库的同学来说,算是很友好的一个入门工具。

想成为云计算大数据Spark高手,看这里!戳我阅读

年薪50W的Java程序员转大数据学习路线戳我阅读

大数据人工智能发展趋势与前景  戳我阅读

最全最新的大数据系统交流路径!!戳我阅读

2019最新!大数据工程师就业薪资,让人惊艳!戳我阅读

原理


在大数据生态中,hive一般作为数据仓库来使用。什么是数据仓库呢?简单来说就像一个大粮仓,里边堆着各种各样的粮食,比如小麦、玉米、土豆、大米等等。数据仓库里是一个数据集合体,把不同数据源按照一定的形式集合统一起来。 Hive本身是不做数据存储的,它是构建在分布式存储系统HDFS之上,我们平常看到的表数据其实本质上来说还是HDFS的文件。Hive把这些HDFS数据文件,通过元数据规则映射为数据库的表,并且可以提供SQL操作的功能。 Hive总体结构比较简单,下方是整体的hive架构图,我们可以看到,总体有三个组件:用户接口、元数据系统、驱动器。

 

 

 

用户通过用户接口来输入操作指令。一般接口有三种形式:

 

CLI端:一般在linux服务器直接输入hive即可进入;

WEB模式:通过命令bin/hive --service hwi启动,默认访问9999端口;

远程模式:一般是JDBC之类的编程接口;

 

Hive的核心在于驱动器,一般驱动器接收到用户接口传递的一条SQL之后,会进行下面的一系列操作:

  • 驱动器开始进行语法和语义分析

  • 生成逻辑计划并且逻辑优化

  • 生成物理计划

  • 发送计划到执行引擎(常用引擎有mapredue和sprk)执行

  • 结果返回

而元数据系统一般传统数据库来承载,主要记录了包括hive表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等。

 

 

常用hive语法


了解了hive的基础原理之后呢,我们这里结合工作中一些需求,来介绍下开发同学常用的hive操作。

 

  • 分组统计


作为一名SQL仔,经常会要去统计一些奇奇怪怪的指标,比如不同年龄段的UV,下单数的小时分布之类的。一般常用的分组就是group by了,然后配合上一些窗口函数, SUM、AVG、MIN、MAX、COUNT等,就可以实现我们很多统计需求了。比如下边的统计时间段的独立用户数,查询结果如下图所示:

 

 

 

  • 关联查询


有时候我们查询的数据存放在不同的表中,那关联查询就派上用场了。所谓关联查询,一般就是通过两张表相同的字段值关联起来,同时查询两张表的记录。Hive中常用关联分内外关联。

我们先建立两张简单的表tab_a和tab_b,用实例来说明关联机制。表结构和表数据如下图所示:

 

 

内关联一般使用关键字Join或inner join,内关联只返回关联上的结果。

 

 

外关联的形式就比较多样化了,又分为:

 

左外关联:关键字为left [outer] join,以前边的表为主表,返回记录数和主表记录一致,关联不上的字段为null;

 

 

右外关联:关键字为right [outer] join,和左外关联相反,则是以后边的表为主表。

全外关联:full [outer] join,返回两个表的去重之和,关联不上的字段为null。

 

  • 行列转换


有时候我们会遇到这样的需求,需要把多列的数据平铺到一行上输出。比如查询用户的访问轨迹,这时候有两个函数就起上作用了。还是让我们先来看看效果。

这两个sql的作用都是把每个用户的点击轨迹拼接暂展示出来,其中collect_set和collect_set能够把列数据合并,转为一行。而两个的唯一区别就是collect_set会进行去重。

上述讲的是行转列,还有些需求,希望我们能把列数据拆分成多行,比如数据结构如下,

Page_id String

Ad_id Array<int>

A

[1,2,3]

B

[3,5,6]

C

[2,4,5]

 

要统计每个广告在所有页面出现的次数,这时候,我们可以先把同一列的数据线拆成多行,hive提供了explode展开函数,具体效果如下图:

Explode一般配合lateral view使用,把字段内容铺开成虚拟视图。接下来我们再这个基础之上,就可以使用统计函数来进行分析。

 

  • 取TopN记录


给数据分组排序再取前几条记录,也是我们较为常见的需求。hive提供了row_number函数,可以对排序值进行编号。举个栗子,要取省份的温度最高的城市,数据如下:

省份

城市

温度

广东

佛山

34

广东

广州

30

江西

赣州

31

江西

南昌

28

江西

萍乡

29

湖南

长沙

26

湖南

衡阳

25

我们可以使用row_number()组合group by的形式,来进行组内排序,并且返回顺序值rank。

结果如下图所示:

此时,如果要去top1的数据,只需添加rank为1的条件即可。和row_number功能和用法类似的函数还有rank()和dense_rank(),唯一的区别在返回的排序rank值有细微区别,此处不再赘述。

 

Hive进阶


  • 数据倾斜

在我们数据清洗过程中,经常会出现一种现象,分布式任务一般会分成多个小任务task,但是呢,有些task处理的很快,有些task就很慢,有时候甚至会卡死导致整个任务失败,这种现象就是恶名远扬的数据倾斜。之所以导致数据倾斜,大部分是join、去重统计(count distinct)或者group by操作中的key分布不均匀。拿最常见的hive查询引擎mapreduce来说,基本就是shuffle阶段,有些reduce任务获取到的key数据量十分多,导致处理很缓慢。

为了避免数据倾斜,一般从两种方向去解决:

1.调整hive参数

我们可以设置hive.map.aggr和hive.groupby.skewindata两个参数为true,此时hive会生成两个job任务,第一个job先将key进行随机化处理,第二个job在进行真正的shuffle key。如下流程说明图:

 

从上图可以看出,由于多次在map端聚合,使得最终shuffle时的数据量大大减少,从而减轻了数据倾斜的程度。

2.优化sql

  • 使用mapJoin:我们经常会有大小表join的需求,而这也是数据倾斜的多发区。此时我们可以使用mapJoin的方式,从而避免shuffle。具体实现就是把小表在每一个Map任务内存中保存一份,从而直接在Map就进行join操作。没了reduce过程,自然也避免了数据倾斜。在hive0.11版本之前,需要显示声明启动该优化操作,如下示例SQL所示:Select /*+ MAPJOIN(small_tab)*/  .key,value FROM small_tab JOIN big_tab ON small_tab.key = big_tab.key 而在hive0.11版本之后,hive能够自动检测小表,自行进行mapJoin优化。我们可以通过hive.mapjoin.smalltable.filesize参数手动配置小表的阈值(默认值25M)。使用MapJoin有一个缺点在于内存会浪费,因为每个Map端都有一个副本。所以mapJoin也一般只适合大小表join的情况。

 

  • 异常值、特殊值手动处理:很多时候造成数据倾斜的可能是一些空值或者,字符串导致的。我们可以通过过滤空值或者对空值做随机字符串处理,由此避免空值的影响。

 

  • 如果是大表和大表的join产生了数据倾斜,mapJoin这种方式不太合适,但是在某些场景下,其中一个大表可以被处理成小表。比如,我们要查询单日访客浏览记录,并需要附加用户信息。这时候要和用户大表user_info关联,而单日访客记录量user_flow也比较大,并不能直接使用mapjoin的方式。但仔细分析,单日访客UV其实并不大,可以先进行简单去重,转换为小表进而可以使用mapJoin。具体SQL如下所示:select /*+mapjoin(x)*/* from user_flow a left outer join (select /*+mapjoin(c)*/d.* from ( select distinct user_id from user_flow )c join user_info d on c.user_id = d.user_id) x on a.user_id =

    引语


    大数据开发之路漫漫其修远兮,吾将上下而求索。很多入门大数据的小伙伴,可能第一个接触到的,就是一只可爱的“小象”,也就是我们的大数据领域的数据仓库工具hive。



     

     


    这只小象给我们提供了方便类SQL查询语言HQL来操纵数据,使得我们一开始不用编写复杂的代码,就可以轻松的探索数据。Hive对于熟悉传统数据库的同学来说,算是很友好的一个入门工具。

     

    原理


    在大数据生态中,hive一般作为数据仓库来使用。什么是数据仓库呢?简单来说就像一个大粮仓,里边堆着各种各样的粮食,比如小麦、玉米、土豆、大米等等。数据仓库里是一个数据集合体,把不同数据源按照一定的形式集合统一起来。 Hive本身是不做数据存储的,它是构建在分布式存储系统HDFS之上,我们平常看到的表数据其实本质上来说还是HDFS的文件。Hive把这些HDFS数据文件,通过元数据规则映射为数据库的表,并且可以提供SQL操作的功能。 Hive总体结构比较简单,下方是整体的hive架构图,我们可以看到,总体有三个组件:用户接口、元数据系统、驱动器。

     

     

    用户通过用户接口来输入操作指令。一般接口有三种形式:

     

    CLI端:一般在linux服务器直接输入hive即可进入;

    WEB模式:通过命令bin/hive --service hwi启动,默认访问9999端口;

    远程模式:一般是JDBC之类的编程接口;

     

    Hive的核心在于驱动器,一般驱动器接收到用户接口传递的一条SQL之后,会进行下面的一系列操作:

  • 驱动器开始进行语法和语义分析

  • 生成逻辑计划并且逻辑优化

  • 生成物理计划

  • 发送计划到执行引擎(常用引擎有mapredue和sprk)执行

  • 结果返回

  • 而元数据系统一般传统数据库来承载,主要记录了包括hive表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等。

     

     

    常用hive语法


    了解了hive的基础原理之后呢,我们这里结合工作中一些需求,来介绍下开发同学常用的hive操作。

     

  • 分组统计


  • 作为一名SQL仔,经常会要去统计一些奇奇怪怪的指标,比如不同年龄段的UV,下单数的小时分布之类的。一般常用的分组就是group by了,然后配合上一些窗口函数, SUM、AVG、MIN、MAX、COUNT等,就可以实现我们很多统计需求了。比如下边的统计时间段的独立用户数,查询结果如下图所示:

     

     

  • 关联查询


  • 有时候我们查询的数据存放在不同的表中,那关联查询就派上用场了。所谓关联查询,一般就是通过两张表相同的字段值关联起来,同时查询两张表的记录。Hive中常用关联分内外关联。

    我们先建立两张简单的表tab_a和tab_b,用实例来说明关联机制。表结构和表数据如下图所示:

     

    内关联一般使用关键字Join或inner join,内关联只返回关联上的结果。

     

     

    外关联的形式就比较多样化了,又分为:

    左外关联:关键字为left [outer] join,以前边的表为主表,返回记录数和主表记录一致,关联不上的字段为null;

     

    右外关联:关键字为right [outer] join,和左外关联相反,则是以后边的表为主表。

    全外关联:full [outer] join,返回两个表的去重之和,关联不上的字段为null。

     

  • 行列转换


  • 有时候我们会遇到这样的需求,需要把多列的数据平铺到一行上输出。比如查询用户的访问轨迹,这时候有两个函数就起上作用了。还是让我们先来看看效果。

     

    这两个sql的作用都是把每个用户的点击轨迹拼接暂展示出来,其中collect_set和collect_set能够把列数据合并,转为一行。而两个的唯一区别就是collect_set会进行去重。

  •  

    上述讲的是行转列,还有些需求,希望我们能把列数据拆分成多行,比如数据结构如下,

    Page_id String

    Ad_id Array<int>

    A

    [1,2,3]

    B

    [3,5,6]

    C

    [2,4,5]

     

    要统计每个广告在所有页面出现的次数,这时候,我们可以先把同一列的数据线拆成多行,hive提供了explode展开函数,具体效果如下图:

  •  

    Explode一般配合lateral view使用,把字段内容铺开成虚拟视图。接下来我们再这个基础之上,就可以使用统计函数来进行分析。

     

  • 取TopN记录


  • 给数据分组排序再取前几条记录,也是我们较为常见的需求。hive提供了row_number函数,可以对排序值进行编号。举个栗子,要取省份的温度最高的城市,数据如下:

    省份

    城市

    温度

    广东

    佛山

    34

    广东

    广州

    30

    江西

    赣州

    31

    江西

    南昌

    28

    江西

    萍乡

    29

    湖南

    长沙

    26

    湖南

    衡阳

    25

    我们可以使用row_number()组合group by的形式,来进行组内排序,并且返回顺序值rank。

    结果如下图所示:

    此时,如果要去top1的数据,只需添加rank为1的条件即可。和row_number功能和用法类似的函数还有rank()和dense_rank(),唯一的区别在返回的排序rank值有细微区别,此处不再赘述。

     

    Hive进阶


  • 数据倾斜

  • 在我们数据清洗过程中,经常会出现一种现象,分布式任务一般会分成多个小任务task,但是呢,有些task处理的很快,有些task就很慢,有时候甚至会卡死导致整个任务失败,这种现象就是恶名远扬的数据倾斜。之所以导致数据倾斜,大部分是join、去重统计(count distinct)或者group by操作中的key分布不均匀。拿最常见的hive查询引擎mapreduce来说,基本就是shuffle阶段,有些reduce任务获取到的key数据量十分多,导致处理很缓慢。

    为了避免数据倾斜,一般从两种方向去解决:

    1.调整hive参数

    我们可以设置hive.map.aggr和hive.groupby.skewindata两个参数为true,此时hive会生成两个job任务,第一个job先将key进行随机化处理,第二个job在进行真正的shuffle key。如下流程说明图:

     

    从上图可以看出,由于多次在map端聚合,使得最终shuffle时的数据量大大减少,从而减轻了数据倾斜的程度。

    2.优化sql

  • 使用mapJoin:我们经常会有大小表join的需求,而这也是数据倾斜的多发区。此时我们可以使用mapJoin的方式,从而避免shuffle。具体实现就是把小表在每一个Map任务内存中保存一份,从而直接在Map就进行join操作。没了reduce过程,自然也避免了数据倾斜。在hive0.11版本之前,需要显示声明启动该优化操作,如下示例SQL所示:Select /*+ MAPJOIN(small_tab)*/  .key,value FROM small_tab JOIN big_tab ON small_tab.key = big_tab.key 而在hive0.11版本之后,hive能够自动检测小表,自行进行mapJoin优化。我们可以通过hive.mapjoin.smalltable.filesize参数手动配置小表的阈值(默认值25M)。使用MapJoin有一个缺点在于内存会浪费,因为每个Map端都有一个副本。所以mapJoin也一般只适合大小表join的情况。

  •  

  • 异常值、特殊值手动处理:很多时候造成数据倾斜的可能是一些空值或者,字符串导致的。我们可以通过过滤空值或者对空值做随机字符串处理,由此避免空值的影响。

  •  

  • 如果是大表和大表的join产生了数据倾斜,mapJoin这种方式不太合适,但是在某些场景下,其中一个大表可以被处理成小表。比如,我们要查询单日访客浏览记录,并需要附加用户信息。这时候要和用户大表user_info关联,而单日访客记录量user_flow也比较大,并不能直接使用mapjoin的方式。但仔细分析,单日访客UV其实并不大,可以先进行简单去重,转换为小表进而可以使用mapJoin。具体SQL如下所示:select /*+mapjoin(x)*/* from user_flow a left outer join (select /*+mapjoin(c)*/d.* from ( select distinct user_id from user_flow )c join user_info d on c.user_id = d.user_id) x on a.user_id = b.user_id;

  • 好的技术人有三种境界:

    1、做好自己的技术,写出优秀的代码,一方水土,养一个技术人
    2、技术驱动业务,做出优秀的产品,让世界变得更好一些。
    3、创造并制定工业标准,推动世界前行。

     

    ——MacTalk

     

    优势和不足


    Hive目前作为业内使用最为广泛的数据仓库工具,自然有着很多优点:高可靠、容错性高、扩展性强。

    HQL语法和传统SQL类似,且内置大量处理函数支持的存储格式种类多,兼容性强。用户接口多,支持各种形式的调用。但是hive也有它自身的一些不足,比如:

    OLTP支持不足,不支持事务,目前只有比较新的版本才可以实现行列级别更新且对格式要求严格。

    由于HDFS特性数据处理延迟高效率较低。HQL的表达能力和灵活性方面有限。基于这些优缺点,hive有它自身擅长的领域,比如用作离线数据仓库,批量处理海量数据。如果要追求实时性或者要高效率处理小量数据,目前来看,其他新的技术方案,比如kudu、hbase等或许是更好的选择。

     

     

    AI

     

    b.user_id;

 

优势和不足


Hive目前作为业内使用最为广泛的数据仓库工具,自然有着很多优点:高可靠、容错性高、扩展性强。

HQL语法和传统SQL类似,且内置大量处理函数支持的存储格式种类多,兼容性强。用户接口多,支持各种形式的调用。但是hive也有它自身的一些不足,比如:

OLTP支持不足,不支持事务,目前只有比较新的版本才可以实现行列级别更新且对格式要求严格。

由于HDFS特性数据处理延迟高效率较低。HQL的表达能力和灵活性方面有限。基于这些优缺点,hive有它自身擅长的领域,比如用作离线数据仓库,批量处理海量数据。如果要追求实时性或者要高效率处理小量数据,目前来看,其他新的技术方案,比如kudu、hbase等或许是更好的选择。

 

 

AI

 

好的技术人有三种境界:

1、做好自己的技术,写出优秀的代码,一方水土,养一个技术人
2、技术驱动业务,做出优秀的产品,让世界变得更好一些。
3、创造并制定工业标准,推动世界前行。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值