Hive是一款建立在Hadoop之上的开源数据仓库
系统,可以将存储在Hadoop文件中的结构化、半结构化数据文件映射为一张数据库表
,基于表提供了一种类似SQL的查询模型,简称为Hive语言查询(HQL)
,用于访问和分析存储在Hadoop文件中的大型数据集
hive核心是将HQL转换为MapReduce程序,然后将程序提交给Hadoop集群执行
.
使用Hadoop MapReduce直接处理数据面临着以下问题:
使用Hive处理数据的好处:
从功能上说,数据仓库软件至少具备两种能力:存储数据能力、分析数据能力
Hive作为一款大数据时代的数据仓库软件,当然也具备上述两种能力,只不过hive并不是自己实现了上述的两种能力,而是借助了Hadoop。Hive利用HDFS存储数据,借助MapReduce 查询分析数据
,看上去好像全是Hadoop,实际上hive最大的魅力在于用户专注于编写HQL,hive帮你转换成MapReduce程序完成对数据的分析
架构图
包括CLI、JDBC/ODBC、web GUI,其中CLI(Command line interface)为Shell命令行,Hive中的Thrift服务器允许外部客户端通过网络与Hive进行交互,类似于JDBC或者ODBC协议,web GUI是通过浏览器访问Hive的
通常是存储在关系数据库如MySQL/derby中,hive中的元数据包括表的名字、表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录
完成HQL查询语句从词法分析、语法分析、编译、优化以及查询计划的生成,生成查询计划存储在HDFS中,并在随后由执行引擎调用执行
Hive本身并不直接处理数据文件,而是通过执行引擎处理,当下Hive支持MapReduce、Tez、Spark 3中执行引擎
数据模型: 用来描述数据、组织数据和对数据进行操作,是对显示时间数据特征的描述,Hive的数据模型类似于RDBMS库表结构的模型,此外还有自己特有的模型。Hive数据可以在粒度级别上分为三类:
Hive 作为一个数据仓库,在结构上积极向传统数据库看齐,也分数据库(Schema),每个数据库下面有各自的表组成,默认数据库default
Hive的数据都是存储在HDFS上的
,默认有一个根目录,在hive-site.xml中由参数 hive.metastore.warehousr.dir指定,默认值为/user/hive/warehouse
因此Hive中的数据库在HDFS上的存储路径为: ${hive.metastore.warehouse.dir}/databasename.db
Hive表与关系数据库中的表相同,Hive中的表所对应的数据通常是存储在HDFS中,而表相关的元数据锁是存储在RDBMS中
Hive中表结构存储在HDFS上的存储路径为${hive.metastore.warehouse.dir}/databasename.db/tablename
Partition 分区时Hive的一种优化手段表,分区是指根据分区列(例如 日期 day)的值将表划分为不同的分区
,这样子可以更快的对指定分区数据进行查询
分区在存储层面上的表现为:table表目录下以子文件夹形式存在,一个文件夹表示一个分区
,子文件夹命名标准: 分区列=分区值
Hive还支持分区下继续创建分区,所谓的多重分区。
Bucket分桶表时Hive的一种优化手段,分桶是指根据表中字段(例如 标号ID)的值经过hash计算规则将数据文件划分成指定的若干个小文件,
分桶规则hashfunc(字段)%桶的个数
,余数相同的分到同一个文件中
分桶的好处时可以优化join查询和方便抽样查询
。Bucket分桶表在HDFS中的表现为 同一个目录下数据根据hash散列之后编程若干个文件
hive虽然具有RDBMS数据库的外表,包括数据模型、SQL语法都十分相似,但是应用场景却完全不同,Hive适合用来做海量数据的离线分析,Hive的定位是数据仓库,分析面向OLAP系统
Hive | MySQL | |
---|---|---|
定位 | 数据仓库 | 数据库 |
查询语言 | HQL | SQL |
使用场景 | 离线数据分析 | 业务数据事务处理 |
数据存储 | HDFS | Local FileSystem |
执行引擎 | MR、Tez、Spark | Excutor |
执行延迟 | 高 | 低 |
处理数据规模 | 大 | 小 |
常见操作 | 导入数据、查询 | 增删改查 |
什么是元数据? 元数据,是描述数据的数据。主要是描述属性的信息,用来支持如指示存储位置、历史数据、资源查询、文件记录等功能
Hive Metadata
即Hive的元数据,包括用hive创建的database、table、表的位置、类型、属性、字段顺序类型等元信息。元数据存储在关系型数据库中,如hive内置的Derby或者第三方,如MySQL。
Hive Metastore
即Hive元数据服务,Metastore服务的作用是管理metadata元数据,对外暴露服务地址,让各种客户端通过连接metastore服务,由metastore再去连接MySQL数据库来存取元数据。
有了metastore服务,就可以有多个客户端同时连接,而且这些客户端不需要知道MySQL数据库的用户名和密码,只需要连接metastore服务即可。某种程度上也保证了hive元数据的安全性
metastore服务配置有三种模式:内嵌模式、本地模式、远程模式,区分三种配置方式的关键未提示弄清楚两个问题:
内嵌模式 | 本地模式 | 远程模式 | |
---|---|---|---|
Metastore单独配置、启动 | 否 | 否 | 是 |
Metadata存储介质 | Derby | MySQL | MySQL |
在这里我们省略了一些前置步骤,比如说Hadoop分布式集群搭建等操作
内嵌模式是metastore默认的部署模式,这种模式下,元数据存储在内置的Derby数据库
,并且Derby数据库和metastore服务都内嵌在HiveServer进程中,当启动HiveServer进程时,Derby和metastore都会启动,不需要额外启动Metastore服务
,但是一次只能支持一个活动用户,适用于测试体验,不适用于开发环境
内嵌模式特征就是不需要安装数据库,不需要配置启动Metastore服务,解压安装包初始化即可。
需要注意的是Hive版本需要手动进行元数据初始化
操作
hive需要根据自己的版本进行选择,我这里的Hadoop版本是3.3.1,可以使用hive3.x版本,所以在这里选择了hive3.1.1
解压
tar -zxvf apache-hive-3.1.3-bin.tar.gz
查看解压出来的成果:
由于个人习惯,我需要把他给移动/复制到其他路径下
cp -r apache-hive-3.1.3-bin /opt/module/hive
解决Hadoop、Hive之间guava版本差异问题
直接移除hive下lib中的guava,然后将Hadoop目录下share/hadoop/common/lib
下的guava复制过来即可,我在这里直接全部完成
# 移除hive中的guava
rm -rf lib/guava-19.0.jar
# 将Hadoop中的guava给复制过来
cp ../hadoop-3.3.1/share/hadoop/common/lib/guava-27.0-jre.jar lib/
# 查询是否已经复制过去了
ls lib |grep gua
修改hive的配置文件
hive3.0以上的版本,配置文件大多数都是给你一个模板,然后你自己进去配置,在这里我们需要修改hive的环境变量,就需要先拿到他的配置文件
cp hive-env.sh.template hive-env.sh
随后我们在配置文件中指定JAVA_HOME、HADOOP_HOME、HIVE_AUX_JARS_PATH(jar包路径)和HIVE_CONF_DIR(配置文件路径)即可
export HIVE_CONF_DIR=/opt/module/hive/conf
export JAVA_HOME=/opt/module/jdk1.8.0_301
export HADOOP_HOME=/opt/module/hadoop-3.3.1
export HIVE_AUX_JARS_PATH=/opt/module/hive/lib
初始化
现在我们回到我们的hive的路径下,然后开始进行初始化
bin/schematool -dbType derby -initSchema
最后可以看到说编译成功,那么jiu’zhen’de’c就真的成功了
尝试
在这里如果想要运行hive,必须先启动Hadoop! 必须先启动Hadoop!必须先启动Hadoop!
后续全是在Hadoop正常运行的情况下操作的,不再进行提示
直接bin/hive
启动hive
HQL的语法与SQL语法很相似,在这里我直接查看数据库
show databases;
create database wxk;
现在我们创建一个为wxk
的数据库
现在已经创建成功了,出去后发现了一个log文件
我们在上文说它适合单用户,现在我们去另一个地方,我们进入到bin下直接启动hive,发现正常启动,现在我们尝试执行命令:
show databases;
发现报错了,说无法实例化,应该是我们没有进行初始化,那么我在这里在进行一次初始化
./schematool -dbType derby -initSchema
我们在进入到hive中,查看数据库发现:
wxk
这个数据库没有了,这就是hive内嵌模式的问题,在哪里初始化,元数据文件就存放在哪里,当我们换个目录启动hive 他就说说不存在元数据,初始化之后必然找不到元数据
本地模式下,Metastore服务与主HiveServer进程在同一进程中运行,但是存储元数据的数据库在单独的进程中运行,并且可以在单独的主机上。metastore服务将通过JDBC与metastore数据库进行通信。
本地模式采用外部数据库来存储元数据,这里使用的是MySQL
hive根据hive.metastore.uris参数值来判断,如果为空,则表示本地模式,缺点是每次启动hive服务,都内置启动了一个metastore
本地模式和远程模式都需要MySQL,MySQL安装仅在此处进行一个演示
在这里我们去MySQL 官网下载一个相关的rpm包,但是我不想一点点安装,我直接偷懒,我这里选择yum安装,主打一个省事,剩下的根据自己的版本进行一个选择
接下来就简单了
rpm -ivh mysql80-community-release-el7-7.noarch.rpm
yum install mysql-server
如果中间需要输入,直接y
即可,现在我们查看MySQL服务是否启动
systemctl status mysqld.service
systemctl start mysqld
现在我们要进入到MySQL中,为其设置密码、远程登录用户,但是MySQL在安装成功后就会自己生成一个密码,我们需要这个临时密码邓丽
grep "password" /var/log/mysqld.log
OK 现在可以进入到MySQL中
mysql -uroot -p
# 然后输入这个临时密码就行 建议复制,因为省事, xshell复制 ctrl+insert 粘贴 shift + insert
# 进入后修改密码
alter user 'root'@'localhost' identified by '密码 大小写+数字';
# 进入到mysql 数据库
use mysql;
# 设置远程访问账号
create user 'root'@'%' identified with mysql_native_password by '密码 大小写+数字';
# 分配权限
grant all on *.* to 'root'@'%';
# 刷新权限
FLUSH PRIVILEGES
OK,接下来尝试远程连接,如果成功,那就算大事完成,使用Navicat 或者DataGrip都可以
远程连接成功
兄弟们,我们在上面已经进行过内嵌模式的安装了,在这里就稍微省略一点,这里无非就是多了一个配置文件hive-site.xml
<configuration>
<property>
<name>javax.jdo.option.ConnectionURLname>
<value> jdbc:mysql://hadoop133:3306/hive?createDatabaseIfNotExist=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8value>
property>
<property>
<name>javax.jdo.option.ConnectionDriverNamename>
<value>com.mysql.cj.jdbc.Drivervalue>
property>
<property>
<name>javax.jdo.option.ConnectionUserNamename>
<value>rootvalue>
property>
<property>
<name>javax.jdo.option.ConnectionPasswordname>
<value>Wxk.20020219value>
property>
<property>
<name>hive.metastore.event.db.notification.api.authname>
<value>falsevalue>
property>
<property>
<name>hive.metastore.schema.verificationname>
<value>falsevalue>
property>
configuration>
因为要连接MySQL,需要用到JDBC,我们就需要下载对应的JDBC驱动放入到lib
中,我们驱动下载页选择我们需要下载的驱动,这里使用的是Java,俺么我们到这里去找
进去后下载解压,把里面的jar包拖到hive的lib下即可
随后我们在hive目录下输入一下命令
bin/schematool -initSchema -dbType mysql -verbos
出现这个表明初始化完成
也可以查看MySQL中是否存在hive这个库
我这里已经出现了这个库,表明已经成功
接下来直接启动即可。
远程模式下,Metastore服务在其自己的单独JVM上运行
,并不在HiveServer的JVM上运行,如果其他进程希望与Metastore服务器通信,则可以使用Thrift Network API进行通信
远程模式下,需要配置hive.metastore.uris参数来指定metastore服务运行的机器IP和端口,并且需要单独手动启动metastore服务
,元数据也采用外部数据库来存储元数据,推荐使用MySQL。
在生产环境中,建议使用远程模式来配置Hive Metastore,这种情况下,其他依赖hive的软件都可以通过metastore 访问hive,由于还可以完全屏蔽数据库层,也带了更好的可管理性/安全性
这里的安装和本地安装大同小异,区别在于配置文件hive-site.xml
不同,以及多了一个步骤,新的hive-site.xml
文件:
<configuration>
<property>
<name>javax.jdo.option.ConnectionURLname>
<value> jdbc:mysql://hadoop133:3306/hive?createDatabaseIfNotExist=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8value>
property>
<property>
<name>javax.jdo.option.ConnectionDriverNamename>
<value>com.mysql.cj.jdbc.Drivervalue>
property>
<property>
<name>javax.jdo.option.ConnectionUserNamename>
<value>rootvalue>
property>
<property>
<name>javax.jdo.option.ConnectionPasswordname>
<value>Wxk.20020219value>
property>
<property>
<name>hive.server2.thrift.bind.hostname>
<value>hadoop133value>
property>
<property>
<name>hive.metastore.urisname>
<value>thrift://hadoop133:9083value>
property>
<property>
<name>hive.metastore.event.db.notification.api.authname>
<value>falsevalue>
property>
<property>
<name>hive.metastore.schema.verificationname>
<value>falsevalue>
property>
configuration>
整体看下来多了一个远程模式部署metastore 服务地址
我们在上文中说到,远程连接的话metastore
需要自己单独启动,随后所有的依赖于hive的软件都通过metastore进行访问,这样子一定程度上可以提高安全性
那么如何启动metastore
呢?
nohup bin/hive --service metastore &
这样子就可以启动,启动成功后会有相应的日志输出文件,如果不启动metastore
直接启动hive,会发生什么?
直接在这里说没有找到元数据存储服务,说明我们需要开启
我们输入指令后会多出来一个日志文件:
我们重新启动hive并尝试输入指令:
OK安装完成
hive发展至今,总共经历了两代客户端工具:
:bin/hive
,是一个shellUtil,主要功能是:
bin/beeline,是一个JDBC客户端
,是官方强烈推荐使用的hive命令工具,与第一代客户端相比较,性能加强安全性提高BeanLine在内嵌模式还是远程模式都可以工作。在内嵌模式下,它运行嵌入式hive(类似于hive client),而在远程模式下beeline通过Thrift连接到单独的HiveServer2服务上
.
HiveServer、HiveServer2都是Hive自带的两种服务,允许客户端再不启动CLI(命令行)的情况下对Hive中的数据进行操作
,并且两个都允许远程客户端使用多种编程语言如Java、python等想hive提交请求,取回结果,但是HiveServer不能处理多于一个客户端的并发请求,于是被重写得到了HiveServer2,HiveServer已经被舍弃。HiveServer2支持多客户端的并发和身份认证,旨在为开放API客户端如JDBC、ODBC提供更好的支持
。Hive通过Metastore服务读写元数据,所以在远程模式下,启动HiveServer2之前必须先要启动metastore服务。
需要注意的是,远程模式下,Beeline客户端只能通过HiveServer2服务访问Hive,而bin/hive是通过Metastore服务访问的
在hive安装包的bin目录下,有hive提供的第一代客户端bin/hive,该客户端可以通过hive的metastore服务,从而达到操作hive的目的。
我们在远程启动玩hive metastore服务之后,可以在其他机器上直接使用不需要任何的配置:
在这里做一个演示:
在hadoop134上创建新的hive
# 从 Hadoop133 上拷贝过来
rsync apache-hive-3.1.3-bin.tar.gz root@hadoop134:/opt/software/
# 在 hadoop134 上进行解压
tar -zxvf apache-hive-3.1.3-bin.tar.gz
# 移动位置
cp -r apache-hive-3.1.3-bin /opt/modul/hive
# 消除hadoop与hive之间guava的差异
cd /opt/modul/hive/lib
rm -r guava-19.0.jar
cp /opt/module/hadoop-3.3.1/share/hadoop/common/lib/guava-27.0-jre.jar ../lib/
# 修改环境变量
cd /opt/modul/hive/conf
cp hive-env.sh.template hive-env.sh
vim hive-env.sh
# 修改hive-site.xml 指向远程服务
vim hive-site.xml
# #####环境变量相关配置
export HIVE_CONF_DIR=/opt/module/hive/conf
export JAVA_HOME=/opt/module/jdk1.8.0_301
export HADOOP_HOME=/opt/module/hadoop-3.3.1
export HIVE_AUX_JARS_PATH=/opt/module/hive/lib
hive-site.xml
配置文件
<configuration>
<property>
<name>hive.metastore.urisname>
<value>thrift://hadoop133:9083value>
property>
configuration>
直接启动:
# 在hive目录下
bin/hive
直接启动可以启动成功,我们在Hadoop133中曾创建一个wxk数据库,现在直接查看hadoop134中是否存在:
beeline客户端不是直接访问metastore服务的,而是需要单独启动hiveserver2服务。在hive安装的服务器上要首先启动metastore服务,然后启动hiveserver2服务
# 启动metastroe服务
nohup bin/hive --service metastore &
#启动hiveserver2 服务
nohup bin/hive --service hiveserver2 &
我是在hadoop133客户端上启动的服务,现在通过hadoop134使用客户端进行访问,需要注意的是hiveserver2服务启动之后需要稍等一段时间才会对外提供服务
Bealine是JDBC的客户端,通过JDBC协议和Hiveserver2服务进行通信,通信地址是jdbc:hive2://hadoop133:10000
bin/beeline
之后我们要输入命令进行连接
! connect jdbc:hive2://hadoop133:10000
之后我们可以看到他让我们输入用户名和密码,用户名我们输入root
,密码直接回车,结束
随后就进入到了相关页面:
我直接一个show databases;
一看究竟:
OK完成
在Hive 中,语法基本上和MySQL的一致,但是使用insert+values语句插入数据,底层由于是MapReduce执行的,效率十分低下,此时回到Hive的本质上:可以将结构化的数据文件映射成一张表,并提供基于表的SQL查询分析。
这里对 Insert values 做做一个演示
我们进入到wxk
这个数据库中,查看有没有表:
现在是什么都没有,那么我们创建一张表,叫做tb_user1
,字段信息如下
id | name | age | |
---|---|---|---|
类型 | int | varchar(255) | int |
建表语句:
create table tb_user1(id int,name varchar(255),age int);
我们再次查看数据库中的表:
show tables;
insert into table tb_user1 values(1,"wxk",20);
执行之后我们发现比较慢,打印了一堆日志,仔细一看,这不是mapreduce嘛:
最后一看跑了100s,将近一分钟?
现在为了去证实这个,我们去yarn集群上查看有没有记录,我的yarn集群web UI访问地址为hadoop132-father:8088
,每个人设置的可能不一样,建议根据自己的配置进行查看,进去之后一看,好家伙,还真是MapReduce程序啊
初体验2 表的映射
我们上文中发现,通过类似于MySQL语法对hive进行插入操作十分缓慢,直接跑了100s,要是每次插入都这慢那岂不是效率低下?在这里我们要强调一下:Hive是数据仓库而不是数据库,hive可以将结构化的数据文件映射成一张表,并提供基于表的SQL查询分析。
,那么我们如何映射?
在这里我们先创建一个结构化的数据文件,我这里直接偷懒:
我把这张表上传到Hadoop的/hivetest
路径下。现在我们根据我们的字段再次创建一个表 好像都一样,不管啦:
create table tb_user1(id int,name varchar(255),age int);
现在我们创建成功,数据也上传到hive了,那么这张表会不会就有数据了?我们直接进行一个查询:
select * from tb_user1;
空空如也,说明虽然我们将数据上传到了Hadoop但是hive并没有加载他,所以我们需要做一些手脚让hive加载数据,这时候该怎么搞?难道说数据文件要放置在表对应的HDFS路径下才可以成功?
在默认情况下,hive会在hdfs的/usr/hive/warehouse中创建自己的路径,我们进行查看:
在这里我们看到了自己的数据库,发现可以点进去,点进去可以看到表明,也是一个文件夹
难道说数据要存放到这里?不管了先试一试。我们把数据从/hivetest
下的user.txt
拷贝到我们的表的文件夹下/user/hive/warehouse/wxk.db/tb_user1
hadoop fs -cp /hivetest/user.txt /user/hive/warehouse/wxk.db/tb_user1/
现在我们再次查看进行查询:
可以看到好像有数据,但是又好像没有数据,你说有吧,它全是null,你说没有吧他有三条和你的一一对应0.0
那么有没有可能是因为hive 不能够识别我们的分隔符?在数据中,我们使用,
都好作为分隔符,是不是需要其他操作让其识别?
我们在创建第二个表,并指定,
是分隔符:
create table tb_user2(id int,name varchar(255),age int) row format delimited fields terminated by ',';
hadoop fs -cp /hivetest/user.txt /user/hive/warehouse/wxk.db/tb_user2/
现在我们再查询一下:
OK数据查询成功,没有什么问题,我们大胜利!
现在我还有一个问题,如果数据类型之间不对应会怎么办?会不会自动调整?我们来试一试:
create table tb_user3(id varchar(255),name int,age int) row format delimited fields terminated by ',';
拷贝数据
hadoop fs -cp /hivetest/user.txt /user/hive/warehouse/wxk.db/tb_user3/
在hive中进行一个查询,结果如下:
发现能转换的都转换了,不能转换的就直接Null ,因为是Java,我们知道这种字符串转成数字直接报错,这里应该是进行了一个异常处理?不管了,反正Hive不帮你调整啥的。难办?那就别办了(掀桌)
在hive中创建表要跟结构化文件映射成功,要注意以下几个问题:
创建表,字段顺序、字段类型要和文件保持一致