分布式SQL计算
Apache HIVE是分布式SQL计算工具,主要功能是
将SQL翻译成MapReduce程序运行,写的是SQL,但是执行的MapReduce
- 接口使用类SQL语法,简单易上手
- 底层执行MapReduce,能够完成分布式SQL计算
模拟实现Hive功能
Select city, count(*) From t_user group by city
-
存在问题
- 数据文件在哪
- 使用什么符号作为列分隔符
- 那些列作为city
- city列什么类型数据
-
解决:需要拥有一个元数据管理功能,对相应的信息进行记录
- 数据位置
- 数据结构
- 等对数据进行描述
-
完成SQL到MapReduce的转换
使用一个SQL解析器,能够做到
- SQL分析
- SQL到MapReduce的转换
- 提交MapReduce程序运行,并收集执行结果
Hive基础架构
Hive本身是一个单机工具,只需要部署在一台服务器即可,运行的时候提交分布式运行的MapReduce程序
-
元数据存储
- 存储在关系数据库中
- 元数据包括表名、表列、分区、属性(是否为外部表)、表数据所在目录
- 通过Metastore服务进程提供元数据管理功能
-
驱动程序
- 包括语法解析器、计划编译器、优化器、执行器
- 完成SQL语句的词法分析、语法分析、编译、优化、查询计划
- 生成的查询计划存储在HDFS中,随后由执行引擎调用执行
- 没有具体的服务进程,封装在Hive所依赖的jar中
-
用户接口
- 通过接口用户能够访问Hive,查看Hive中相关的内容,执行一定的操作1692514544475.jpg
- CLI、JDBC/ODBC、WebGUI
- CLI为shell命令行
- WebGUI通过浏览器访问hive
- Thirft服务器允许外部客户端通过网络与Hive进行交互,类似JDBC/ODBC协议
- 提供Hive Shell、ThirftServer等进程向用户提供接口
Hive部署
使用元数据服务时,需要提供一个关系型数据库,因此部署时除了hive本体外,还需要部署关系型数据库
mysql部署
rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
# 更新密钥
rpm -Uvh https://repo.mysql.com//mysql57-community-release-el7-7.noarch.rpm
# 安装mysql yum库
yum -y install mysql-community-server
# 通过yum安装mysql
systemctl start mysqld
# 启动mysql服务
systemctl enable mysqld
# 设置开机自启
systemctl status mysqld
# 查看sql状态
grep 'temporary password' /var/log/mysqld.log
# 第一次部署会生成一个随机密码
mysql -uroot -p
# 进入mysql
set global validate_password_policy=LOW;
# 设置密码等级为low
set global validate_password_length=3;
# 设置密码长度
alter user 'root'@'localhost' identified by '123456';
# 修改密码为123456
grant all privileges on *.* to root@"%" identified by '123456' with grant option;
# 为远程连接设置密码并授予root权限
flush privileges;
# 刷新权限
配置hadoop
需要配置hadoop的代理用户,因为涉及到对HDFS文件系统的访问,需要设置hadoop用户允许代理其他用户
修改core-site.xml文件,并分发到其他节点,重启hdfs集群
<property>
<name>hadoop.proxyuser.hadoop.hosts</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.hadoop.groups</name>
<value>*</value>
</property>
之前在配置hadoop核心节点的时候就已经配置过了
下载安装hive
wget https://archive.apache.org/dist/hive/hive-3.1.3/apache-hive-3.1.3-bin.tar.gz
<!-- 下载hive -->
tar -zxvf apache-hive-3.1.3-bin.tar.gz -C /export/server/
<!-- 解压 -->
ln -s /export/server/apache-hive-3.1.3-bin /export/server/hive
<!-- 设置软连接 -->
wget https://repo1.maven.org/maven2/mysql/mysql-connector-java/5.1.34/mysql-connector-java-5.1.34.jar
<!-- 下载mysql驱动包 -->
mv mysql-connector-java-5.1.34.jar /export/server/hive/lib
<!-- 放到hive的lib文件夹下 -->
配置hive
在hive的conf目录下,创建hive-env.sh文件,输入以下环境变量
export HADOOP_HOME=/export/server/hadoop
export HIVE_CONF_DIR=/export/server/hive/conf
export HIVE_AUX_JARS_PATH=/export/server/hive/lib
在conf目录下,新建hive-site.xml文件
<configuration>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://node1:3306/hive?createDatabaseIfNotExist=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8</value>
</property>
<!-- 这里连接到mysql中的hive表,如果不存在hive表直接创建 -->
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123456</value>
</property>
<!-- 以上内容都在配置jdbc连接mysql -->
<property>
<name>hive.server2.thrift.bind.host</name>
<value>node1</value>
</property>
<property>
<name>hive.metastore.uris</name>
<value>thrift://node1:9083</value>
</property>
<!-- 配置thrift服务 -->
<property>
<name>hive.metastore.event.db.notification.api.auth</name>
<value>false</value>
</property>
<!-- 配置元数据管理器 -->
</configuration>
要注意处理完后要将整个hive文件夹的所属授权给hadoop用户
chown -R hadoop:hadoop apache-hive-3.1.3-bin hive
初始化元数据库
- 在mysql中创建数据库hive
create database hive charset utf8;
- 执行元数据库初始化命令
cd /export/server/hive
bin/schematool -initSchema -dbType mysql -verbos
初始化成功后,会在hive库中新建74张表用于存放相关的元数据
启动hive
- 创建一个hive的日志文件夹
mkdir /export/server/hive/logs
- 启动元数据服务
前台启动
bin/hive --service metastore
后台启动
nohup bin/hive --service metastore >> logs/metastore.log 2>&1 &
- 启动客户端
- hive thriftserver,该方法不能直接写sql,需要外部客户端连接使用
bin/hive --service hiveserver2
- hive shell 方法,该方法启动可以直接写SQL
bin/hive
- hive thriftserver,该方法不能直接写sql,需要外部客户端连接使用
Hive使用
- 创建表
create table test (id int, name string, gender string);
- 插入数据
insert into test values (1,'张三','male'),(2,'李四','female'),(3,'王五','male');
- 查询数据
select gender, COUNT(*) as cnt from test group by gender;
启动HiveServer2
HiveServer2能够允许用户使用客户端连接hive服务,对外启动一个thrift的接口,供外部的客户端使用
先启动metastore服务,在启动hiveserver2服务
nohup bin/hive --service metastore >> logs/metastore.log 2>&1 &
nohup bin/hive --service hiveserver2 >> logs/hiveserver2.log 2>&1 &
启动beeline
bin/beeline
在beeline中操作
!connect jdbc:hive2://node1:10000
此处的用户名为启动hadoop的用户名,未设置密码
Hive语法
数据库
- 创建数据库
create database if not exists myhive;
use myhive;
查看数据库详细信息
desc database myhive;
可以将数据库存放在hdfs指定位置
create database myhive2 location '/myhive2';
- 删除数据库
删除空数据库
drop database myhive;
如果一个数据库下有数据表,那么直接删除数据库就会报错,可以使用强制删除
drop database myhive2 cascade;
数据表
- 创建数据表
create [external] table [if not exists] table_name
[(col_name data_type [COMMENT col_comment], ... ) ]
[COMMENT table_comment]
[PARTITIONED BY (col_name data_type [COMMENT col_comment), ... ]
[CLUSTERED BY (col_name, col_name,....) ]
[SORTED BY (col_name [ASC|DESC] ,....) INTO num_buckets BUCKETS]
[ROW FORMAT row_format]
[STORED AS file_format]
[LOCATION hdfs_path]
一些可选参数
- EXTERNAL,创建外部表
- PARTITIONED BY, 分区表
- CLUSTERED BY, 分桶表
- STORED AS, 存储格式
- LOCATION,存储位置
数据类型和SQL的数据类型大差不差,常见的
- INT
- STRING
- DOUBLE
- VARCHAR
- TIMESTAMP
- DATA
其中STRING和VARCHAR都表示的是变长字符串,在hive中string使用的更多一些
一个简单的创建表示例
create table test(
id int,
name string,
gender string
);
- 删除数据表
drop table test;
-
内部表
- 内部表和外部表的区别
- 内部表
- 未被external关键字修饰的表即为内部表,为普通表,又称管理表
- 内部表的数据存储位置由
hive.metastore.warehouse.dir
参数决定 - 删除内部表会直接删除元数据和存储数据,可以持久化使用
- 内部表不适合和其他工具共享数据
- 外部表
- 被external关键字修饰的是外部表,即关联表
- 外部表指表的数据可以在任何位置,通过location关键字指定
- 该表并不是在hive内部进行管理的,可以随意通过临时连接连接到外部数据上去
- 删除外部表只会删除元数据(即表的信息),不会删除存储的数据
- 创建内部表就是创建一个简单的表
- 内部表的数据在HDFS上是以明文文件存在的,默认的分隔符为"\001",为ASCII码,在部分文本编辑器中会显示SOH
- 在创建表的时候可自定义分隔符
后面create table if not exists stu(id int, name string) row format delimited fields terminated by '\t';
row
以后的内容表示以\t作为分隔符
- 内部表和外部表的区别
-
外部表
外部表的作用主要是用于临时关联数据,外部表本身和数据是相互独立的- 在创建外部表的时候,必须要根据数据的情况设定好分隔符
- 外部表的数据可以从外部数据进行关联,将数据上传到
location
指定的位置后,就能够从中读取到数据 - 也可以先有数据,后创建外部表,外部表指定到该文件所在的地址即可
- 当不知道表示内部表还是外部表的时候,可以通过
desc formatted table_name;
查看表的状态。 - 内部表和外部表的相互转换
要注意区分EXTERNAL
和TRUE
、FALSE
的大小写问题,大小写固定alter table tbl_name set tblproperties('EXTERNAL'='TRUE); <!-- 内部表转外部表 -->
alter table tbl_name set tblproperties('EXTERNAL'='FAlSE'); <!-- 外部表转内部表 -->
- 删除外部表,删除表不会影响表中存储的数据
drop table if exists (table_name);
数据的导入导出
数据加载
- LOAD语法
该方法不通过mapreduce,对于小文件而言加载速度较快
load data [local] inpath 'filepath' [OVERWRITE] into table table_name;
其中的各部分的含义
- load 加载数据
- [local] 数据是否在本地
- 使用local,数据不再hdfs,需要使用file://协议指定Linux路径
- 不使用local,数据在hdfs,可以直接使用路径
- ‘filepath’: 数据所在路径
[overwrite]
: 是否覆盖已存在数据,没有就不覆盖- tbl_name:被加载进的表名,这个表为内部表
要注意,从hdfs文件系统中加载后,源文件会消失,因为本质就是从系统中移动到指定路径下了
- insert select 语法
该方法时从别的表中读取数据写入到目标表中insert [overwrite | into] table tbl_name_1 [partition (partcol=val1, partcol=val2...) [if not exists]] select select_statement1 from from_statement;
- 从
from_statement
表中,根据select_statement1
条件筛选数据,写入到tab_name_1
表中。被select的表可以是内部表也可以是外部表. - 该方法通过mapreduce方法加载数据,小规模数据时速度较慢
- partition:
- 从
数据导出
- insert overwrite
将数据导出到任意目录,可以是Linux,hdfs,还可以是mysql等数据库
语法insert overwrite [local] directory 'path' select_statement1 from from_statement;
- 导出到hdfs上时不加
local
关键字,导出到本地需加 - 不写的话默认使用’\001’作为分隔符,需要指定列分隔符
- 导出到hdfs上时不加
insert overwrite local directory 'path' row format delimited fields terminated by '\t' select * from from_statement;
- 通过hive shell的方式导出
基本语法bin/hive -e "select * from myhive.test_load;" > /home/hadoop/export3/export4.txt <!-- 指定sql --> bin/hive -f export.sql > /home/hadoop/export3/export4.txt <!-- 指定脚本 -->