0


【大数据】Hadoop里的“MySQL”——Hive,干货满满

【大数据】Hadoop里的“MySQL”——Hive,干货满满

在阅读本文前,请确保已经对Hadoop的三大组件(HDFS、MapReduce、YARN)有所了解,如果不太了解的可以移步《深入浅出Hadoop》观看。

如果仅使用MapReduce来操作HDFS中存放的数据,那么学习成本和开发成本都会比较高。于是,Hive的提出就向广大开发者提供了一种利用SQL来查询和计算HDFS文件的方法。


文章脉络

在这里插入图片描述

图1 Hive知识点脑图

Hive架构

Hive作为Hadoop生态系统中的重要一员,它本质上是一个数仓工具。其核心功能是将存储在Hadoop分布式文件系统(HDFS)上的结构化数据文件映射为数据库中的表结构。这一映射过程允许用户通过一种类似SQL的查询语言——即Hive Query Language(HQL)——来执行数据查询和管理操作,极大地简化大数据的处理流程。

  在Hadoop生态系统中,数据文件通常以原始格式存放在HDFS上。如果我们想要对这些数据进行查询和计算,按照传统方法,我们需要编写复杂的MapReduce程序。MapReduce作为一种编程模型,虽然功能强大,但其学习成本较高,编写和维护MapReduce脚本的难度较大,这无疑增加了学习成本和时间成本,对于非程序员或数据分析人员来说尤其如此。

  Hive的出现,为大数据处理提供了一种更加简便的方法。它允许用户使用类似SQL的语句来查询数据,而这些SQL语句在Hive内部会被转换成相应的MapReduce程序。这意味着,有了Hive,即使是不熟悉MapReduce编程的用户也可以轻松地执行复杂的数据分析任务,无需直接编写繁琐的MapReduce代码。

【注意】:尽管Hive在Hadoop生态系统中扮演着重要角色,但它的定位主要是作为一个数据仓库工具,而不是一个需要独立集群部署的服务。它只是一个把SQL解释成MapReduce代码然后提交任务的工具,是不需要集群部署的。

  在架构上,Hive的底层仍然依赖于MapReduce计算框架、YARN资源管理器和HDFS文件系统。需要注意的是,虽然HQL与标准SQL在语法上有很多相似之处,但它并不是完全兼容SQL的。Hive的SQL方言因包含一些特有的功能和限制,因此被称为HQL。

【注意】:不知道大家开发Java Web项目的时候有没有用过SSH架构?Hibernate与MyBatis是地位等同的框架, 当时基于Hibernate开发的SQL一度也称为HQL,注意不要与Hive SQL的简称HQL弄混了。

  HQL和SQL在设计和语法上都有一些差异,可以理解为它们俩有交集(这个交集其实就是大家平常最通用的功能,比如select * from table)。HQL不支持事务但是在查询的写法上比较强大,而SQL面向事务性数据库设计,适用于实时操作,但是写法不像HQL这么五花八门。

请添加图片描述

图2 Hive架构图

  在图2中,我们可以看到一个清晰的架构视图,其中4个最重要的组件如下:

  1、用户接口Client:Hive提供了多种用户接口,以适应不同用户的需求和使用场景。

  首先是CLI(命令行接口),它允许用户通过命令行直接与Hive交互,执行HQL语句和查看查询结果。
  其次是JDBC/ODBC接口,这使得Hive能够被任何支持JDBC或ODBC标准的第三方应用程序所访问,比如商业智能(BI)工具和定制的数据分析应用程序。

【注意】:BI,Business Intelligence,一般是公司内部部门下的一个团队,负责处理部门内部数据与外部对接、数据可视化等等。比如你是某公司外卖事业部的开发人员,想要获取你司单车部门用户骑行数据,那么你需要去找单车部门的BI对接数据。

  2、元数据Metastore:元数据是Hive中关于数据的数据。它包含了数据库、表、列、分区、用户权限以及其他与Hive管理的数据相关的信息。这些元数据存储在Metastore中,它可以是嵌入式的Derby数据库,也可以是独立的MySQL数据库。推荐使用MySQL来存储元数据,因为它支持多用户并发访问,且具有更好的可扩展性和稳定性。通过维护这些元数据,Hive能够跟踪数据的结构和位置,从而在执行查询时能够正确地定位和处理数据。

【注意】:Hive会把结构化数据解析为Hive表,那么这些表的数据如果再存放在HDFS,查一下表信息就要等一段时间,就没法管理了。因此是存在DB中,保证用户体验。

  3、Thrift:Thrift是一个跨语言的服务框架,它允许客户端使用不同的编程语言与Hive进行通信。这意味着,无论开发者使用Java、Python、C++还是PHP等语言,他们都可以通过Thrift定义的接口与Hive进行交互。这种跨语言支持极大地提高了Hive的可用性和灵活性,使得它能够被集成到各种不同的应用和服务中。

【注意】:工作中,算法和数仓人员都会用Python,如果你再偏工程点,Java也会要写。因此等你到实际生产开发中就会发现这些工具为什么要跨语言。。。。因为你极有可能今天这个项目是用Python写的,下个项目是用Java写的,下下个项目又跳到C++了。最近感觉学习能力比专业能力更重要,任务完成是目的,而语言只是手段。

  4、驱动器Driver:驱动器是Hive的核心组件之一,负责处理用户提交的查询请求。主要工作是解析HQL,转换为MapReduce(MR)或Spark作业提交。

【注意】:Spark地位等同于MapReduce,但是比MapReduce快很多。最初Hive的执行引擎是MapReduce,后来Spark也兼容了Hive。因此现在写HQL都使用Spark作为执行引擎,不再用MapReduce了。

HQL

  HQL中有一些让我初次接触时让我比较惊艳的设计和概念,所以这里着重介绍一下它比MySQL更惊艳的地方。HQL基本语法和SQL一致,这里不会介绍。

表类型

  在Hive中,根据数据的处理和管理方式,可以将表分为内部表(也称为管理表)和外部表。

内部表:内部表是Hive中最为常见的一种表类型,由Hive完全管理。当我们在Hive中创建一个内部表时,表的数据实际上被存储在Hive所管理的HDFS上的特定位置。当我们执行删除内部表的命令时,Hive不仅会从其元数据中删除表的记录,而且还会删除在HDFS上与该表关联的所有数据文件。

【注意】:内部表的存储地址是

/user/hive/warehouse/your_db_name.db/table_name

外部表:在Hive中创建外部表时,指定一个指向HDFS上数据文件的外部位置,但Hive并不拥有这些数据。这意味着,当我们删除一个外部表时,Hive仅会从其元数据存储中移除表的元数据信息,而不会删除HDFS上的实际数据文件。

创建表语法

  在用Hive创建表的时候,需要指定一些有趣的分隔符。

  下面是一个创建表的基本例子,展示了如何创建一个内部表:

CREATETABLE[IFNOTEXISTS] table_name (
    column1_name '字段注释',
    column2_name '字段注释',...
    columnN_name '字段注释')[COMMENT'表注释'][ROW FORMAT DELIMITED][FIELDSTERMINATEDBYchar][STORED AS file_format];

  和MySQL比较不同的是下面三个:

  - ROW FORMAT DELIMITED: 指定表的行格式。这通常用于指定字段之间的分隔符。
  - FIELDS TERMINATED BY char: 指定字段之间的分隔符。
  - STORED AS file_format: 指定表的存储格式。常见的存储格式包括

TEXTFILE

,

SEQUENCEFILE

,

ORC

, 和

PARQUET

  也就是说,在创建表时,可以指定每个字段之间的分隔符、行之间的分隔符和文件类型。

【注意】:这不就是excel、csv嘛!你可以直接下载下来然后用pandas加载,只是有可能数据量巨大,你的内存会爆。

分区

  分区表实际上就是把一个表在HDFS上的文件建立独立的文件夹,每个文件夹对应表的一个分区;相当于把一个大数据集分割成了许多小数据集,这样做可以把数据管理的很有条理。并且在使用

where

查询并且指定分区的时候,查询效率也会增加很多。

  创建分区表的语法:

createtable 表(
    字段名 数据类型,...)
partitioned by(字段 数据类型)row format delimited fieldsterminatedby',';

数据导入导出

  Hive中的数据导入与导出有非常多种写法,并且这些写法在不同的场景下很有用,下面列出具有代表性的几个。

一、Insert语句把Hive表导出到HDFS

insert overwrite directory
'hdfs://user/opt/module/hive-3.1.2/datas/'select*from student1;

二、HIVE Shell命令把Hive表导出到HDFS

 hive -e"select * from db_hive.student1"> 0000.txt

【注意】:Insert语句是在Hive的Cli环境下写的。Hive Shell可以在bash环境里写。

一、insert导入HDFS文件到Hive表

loaddata inpath 'hdfs://xxx/xxx/student.txt'
overwrite intotable student4;

二、insert根据HQL查询结果导入到Hive表

insert overwrite table student5
select id,name from student1;

三、create as 根据查询结果创建

createtableifnotexists student6
asselect id,name from student1;

四、通过location指定表的源数据

create external tableifnotexists student6(
    id int,
    name string
)row format delimited fieldsterminatedby','
location '/export/student/data';

【注意】:insert语句分别支持外部文件和查询结果导入,create as 是直接根据查询结果先创建再导入,location是把表关联到一个地址去。写法五花八门,主要还是一看场景、二看怎么做方便工作量小。

函数

  Hive在查询时,除了可以用普通SQL之外,还可以加入函数来处理字段。Hive的函数除了内置函数,还有UDF(用户自定义函数)。UDF非常滴炫酷。

内置函数

  内置函数SQL也有,最简单的有

MIN

MAX

这些,Hive里比较高级的内置函数如下:

collect_list

是一个聚合函数,用于将指定列的所有值收集到一个列表中。当你需要对某一列的所有值进行集合操作时,这个函数非常有用。例如,如果你想要获取一个部门所有员工的姓名列表,可以使用

collect_list

来实现。

SELECT department, collect_list(name)as employee_names
FROM employees
GROUPBY department;
lateral view

是一个非常有用的操作,它允许你将一个表的列值拆分成多行,并与原始表的行进行连接。这在处理数组或映射类型的列时特别有用。结合

explode

函数,你可以将数组或映射中的每个元素都转换成单独的一行。

SELECT id, name, salary
FROM employees
LATERAL VIEW explode(skills)AS skill;
explode

是一个UDTF(User-Defined Table-Generating Function,用户定义的表生成函数),它用于将数组或映射类型的单个列拆分成多行。

explode

通常与

lateral view

一起使用,以便将数组或映射中的每个元素转换成单独的一行。

SELECT id, skill
FROM employees
LATERAL VIEW explode(skills)AS skill;
concat

是一个字符串函数,它用于将多个字符串连接成一个单一的字符串。当你需要将多个列的值合并成一个字符串时,

concat

函数非常有用。

SELECT concat(first_name,' ', last_name)as full_name
FROM employees;
concat_ws

concat

的一个变体,它允许你指定一个分隔符来连接字符串。这在连接列值时提供了更多的灵活性,特别是当你需要在一个特定的分隔符之间插入值时。

SELECT concat_ws('-', first_name, middle_name, last_name)as full_name
FROM employees;

UDF

  UDF允许用户自己定义封装函数,然后调用处理,最常用的就是Java、Python来实现。

Java

  首先,你需要继承Hive提供的类。对于UDF,可以继承

org.apache.hadoop.hive.ql.udf.generic.GenericUDF

类;这个类提供了实现函数的基本框架,包括输入参数的类型检查、执行逻辑的实现等。

  在继承的类中,你需要实现几个抽象方法,这些方法定义了函数的行为。对于UDF,你需要实现

evaluate()

方法。这个方法是函数执行的核心,你需要在这里编写具体的逻辑。

  一旦你的函数实现完成,你需要将它们打包成jar文件,然后将这个jar文件上传到Hive的

lib

目录下。

  在Hive命令窗口中,你可以通过以下命令来创建函数:

# 添加jar包add jar 自定义jar包的路径;# 创建Function,temporary表示添加临时的function
create [temporary]function[if not exists] 函数名称 "自定义函数的全类名";# 删除函数
drop [temporary]function[if exists] 函数名称;

  一旦函数创建成功,你就可以在Hive查询中使用它了。例如,如果你创建了一个名为

my_udf

的UDF,你可以在查询中这样使用:

SELECT my_udf(column1), column2
FROMtable;

【注意】:UDF其实有三种:UDF、UDAF、UFTF,分别表示“一对一”、“多对一”、“一对多”。这里只介绍UDF,主要是和Python的写法比较一下。

Python

  Python 实现的 UDF、UDAF、UDTF 函数,需要对输入的一整行的数据进行处理,而并不是针对某一个字段进行处理!

  读取每一行的输入:可以使用 Python 中的标准输入流来读取。需要注意的是,无论 Hive 的表中是以什么样的字符进行分隔的,这里读取到的字段之间始终是以

\t

进行分隔的!因此我们也必须要使用

\t

进行字段的切割。

  输出一行的数据:在将一整行的数据处理完成之后,如果需要输出的时候,直接使用 print 函数打印即可。与输入的一样,输出的不同的字段之间也必须要使用

\t

进行分隔!

  UDAF 函数实现、UDTF 函数实现:如果实现 UDAF、UDTF 这种输入行和输出行不一致的情况,直接控制 print 函数的输出次数即可。一次的 print 就会生成一行的数据,因此合理控制 print 函数的调用次数,即可实现 UDAF、UDTF 函数。

-- 应用UDF
addfile example.py

-- 处理一列
select transform(t_name) using 'python3 example.py' as (t_name) from example_01;
-- 查询两列
select transform(t_name, t_gender) using 'python3 example.py' as (t_name, t_gender) from example_01;

【注意】:Java的UDF和Python的UDF调用时非常不一样,要牢记。

标签: 大数据 hadoop mysql

本文转载自: https://blog.csdn.net/qq_43592352/article/details/142067831
版权归原作者 征途黯然. 所有, 如有侵权,请联系我们删除。

“【大数据】Hadoop里的“MySQL”——Hive,干货满满”的评论:

还没有评论