Hive
Hive概念
- Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张表,并提供类SQL查询功能
- 本质上:将 HQL 转化成 MapReduce 程序
Hive的优缺点
优点
- 操作接口采用类 SQL 语法,提供快速开发的能力(简单、容易上手)
- 避免写 MapReduce,减少开发人员的学习成本
Hive
的执行延迟比较高,因此 Hive 常用于数据分析,对实时性要求不高的场合Hive
优势在于处理大数据,对于处理小数据没有优势,因为Hive
的执行延迟比较高Hive
支持用户自定义函数,用户可以根据自己的需求来实现自己的函数
缺点
Hive的
HQL`表达能力有限- 迭代式算法无法表达
- 数据挖掘方面不擅长,由于
MapReduce
数据处理流程的限制,效率更高的算法却无法实现
Hive
的效率比较低Hive
自动生成的MapReduce
作业,通常情况下不够智能化Hive
调优比较困难,
HIVE架构原理
- 用户接口:
Client
- 元数据:
Metastore
- 元数据包括:表名、表所属的数据库、表的拥有者、列/分区字段、表的类型(是否是外部表)、表的数据所在目录等
- 默认存储在自带的
derby
数据库中,推荐使用MySQL
存储Metasore
Hadoop
- 使用
HDFS
进行存储,使用MapReduce
进行计算
- 使用
- 驱动器:
Driver
- 解析器(
SQL Parser
):将sql
字符串转换成抽象语法树AST
,这一步一般都用第三方工具完成,比如antir
:对AST
进行语法分析,比如表是否存在、字段是否存在、SQL
语义是否有误 - 编译器(
Physical Plan
):将AST
编译生成逻辑执行计划 - 优化器(
Query Opimizer
):对逻辑执行计划进行优化 - 执行器(
Execution
):把逻辑执行计划转换成可以运行的物理计划,对于Hive来说,就是MR/Spark
- 解析器(
Hive
通过给用户提供的一系列交互接口,接收到用户的指令(SQL
),使用自己的Driver
,结合元数据(MetaStore
),将这些指令翻译成MapReduce
,提交到Hadoop
中执行,最后,将执行返回的结果输出到用户交互接口
Hive
安装
Hive
安装地址
Hive
官网地址- http://hive.apache.org/
- 文档查看地址
- https://cwiki.apache.org/confluence/display/Hive/GettingStarted
- 下载地址
- http://archive.apache.org/dist/hive/
github
地址- https://github.com/apache/hive
Hive
安装部署
-
把
apache-hive-3.1.3-bin.tar.gz
上传到Linux
的/opt/software
目录下 -
解压
apache-hive-3.1.3-bin.tar.gz
到/opt/module/
目录下面 -
修改
apache-hive-3.1.3-bin.tar.gz
的名称为hive
-
修改
/etc/profile.d/my_env.sh
,添加环境变量sudo vim /etc/profile.d/my_env.sh #HIVE_HOME export HIVE_HOME=/opt/module/hive export PATH=$PATH:$HIVE_HOME/bin
-
初始化元数据库(默认是derby数据库)
bin/schematool -dbType derby -initSchema
- tips
- Hive 默认使用 Hadoop 的配置文件来连接到 HDFS。Hadoop 的配置文件通常位于
$HADOOP_HOME/etc/hadoop
目录下,其中包括core-site.xml
和hdfs-site.xml
文件。这些文件中定义了 Hadoop 集群的相关配置,包括 NameNode 的地址和端口号。 - 如果您在安装 Hive 时指定了 Hadoop 的安装目录,那么 Hive 会自动读取 Hadoop 的配置文件来连接到 HDFS。
- 如果您没有指定 Hadoop 的安装目录,那么 Hive 会在默认的位置查找 Hadoop 的配置文件。
- 如果您的 Hadoop 配置文件不在默认位置,那么您需要在 Hive 的配置文件中指定 Hadoop 配置文件的位置。
- Hive 默认使用 Hadoop 的配置文件来连接到 HDFS。Hadoop 的配置文件通常位于
-
启动
Hive
bin/hive
-
另一个会话启动hive,产生报错
- 原因是
Hive
默认使用的元数据库作为derby
,开启Hive
之后就会占用源数据库,且不与其他客户端共享数据,所以需要将Hive
的元数据地址改为MySQL
- 原因是
MySQL安装
-
检查当前系统是否安装过
MySQL
rpm -qa | grep mariadb //如果存在,则卸载 sudo rpm -e --nodeps mariadb-libs
-
卸载系统自带的
mariadb
sudo rpm -qa | grep mariadb | xargs sudo rpm -e --nodeps
-
将
MySQL
安装包拷贝到/opt/software
目录 -
解压
MySQL
安装包
tar -xf mysql-5.7.28-1.el7.x86_64.rpm-bundle.tar -C mysql_lib/
- 执行
rpm
安装
sudo rpm -ivh mysql-community-common-5.7.28-1.el7.x86_64.rpm
sudo rpm -ivh mysql-community-libs-5.7.28-1.el7.x86_64.rpm
sudo rpm -ivh mysql-community-client-5.7.28-1.el7.x86_64.rpm
sudo rpm -ivh mysql-community-server-5.7.28-1.el7.x86_64.rpm
- 初始化
sudo systemctl start mysqld
- 启动 MySQL
sudo systemctl start mysqld
- 查看
MySQL
密码
sudo cat /var/log/mysqld.log | grep password
- 用刚刚查到的密码进入
MySQL
(如果报错,给密码加单引号)
mysql -uroot -p'password'
- 更改
MySQL
密码策略
set global validate_password_policy=0;
set global validate_password_length=4;
- 设置简单好记的密码
set password=password("123456");
- 进入
MySQL
库
use mysql
- 修改
user
表,把Host
表内容修改为%
update user set host="%" where user="root";
配置Hive
元数据存储到MySQL
- 新建
Hive
元数据库
mysql -uroot -p123456
create database metastore;
quit;
- 将
MySQL
的JDBC
驱动拷贝到Hive
的lib
目录下
cp /opt/software/mysql-connector-java-5.1.37.jar $HIVE_HOME/lib
- 在
$HIVE_HOME/conf
目录下新建hive-site.xml
文件
vim $HIVE_HOME/conf/hive-site.xml
- 添加如下内容
<configuration>
<!-- jdbc连接的URL -->
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://hadoop102:3306/metastore?useSSL=false</value>
</property>
<!-- jdbc连接的Driver-->
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<!-- jdbc连接的username-->
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
</property>
<!-- jdbc连接的password -->
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123456</value>
</property>
<!-- Hive默认在HDFS的工作目录 -->
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
</property>
</configuration>
- 初始化
Hive
元数据库(修改为采用MySQL
存储元数据)
bin/schematool -dbType mysql -initSchema -verbose
查看MySQL
中的元数据
- 查看元数据库中存储的库信息
select * from DBS;
- 查看元数据库中存储的表信息
select * from TBLS;
- 查看元数据库中存储的表中列相关信息
select * from COLUMNS_V2;
- 查看元数据中 主键相关信息
select * from KEY_CONSTRAINTS
- 有关
hive
的元数据信息可以查官网
Hive
服务部署
hiveserver2
服务
-
Hive的hiveserver2服务的作用是提供jdbc/odbc接口,为用户提供远程访问Hive数据的功能
-
用户说明
- 在远程访问Hive数据时,客户端并未直接访问
Hadoop
集群,而是由Hivesever2
代理访问。由Hiveserver2的hive.server2.enable.doAs
参数决定,该参数的含义是是否启用Hiveserver2
用户模拟的功能。若启用,则Hiveserver2
会模拟成客户端的登录用户去访问Hadoop
集群的数据,不启用,则Hivesever2
会直接使用启动用户访问Hadoop
集群数据。模拟用户的功能,默认是开启的。
- 在远程访问Hive数据时,客户端并未直接访问
-
hiveserver2部署
-
Hadoop端配置
- hivesever2的模拟用户功能,依赖于Hadoop提供的proxy user(代理用户功能),只有Hadoop中的代理用户才能模拟其他用户的身份访问Hadoop集群。因此,需要将hiveserver2的启动用户设置为Hadoop的代理用户,配置方式如下:
- 修改配置文件core-site.xml
cd $HADOOP_HOME/etc/hadoop vim core-site.xml
- 增加如下配置
<!--配置所有节点的atguigu用户都可作为代理用户--> <property> <name>hadoop.proxyuser.atguigu.hosts</name> <value>*</value> </property> <!--配置atguigu用户能够代理的用户组为任意组--> <property> <name>hadoop.proxyuser.atguigu.groups</name> <value>*</value> </property> <!--配置atguigu用户能够代理的用户为任意用户--> <property> <name>hadoop.proxyuser.atguigu.users</name> <value>*</value> </property>
- Hive端配置,在hive-site.xml文件中添加如下配置信息
<!-- 指定hiveserver2连接的host --> <property> <name>hive.server2.thrift.bind.host</name> <value>hadoop102</value> </property> <!-- 指定hiveserver2连接的端口号 --> <property> <name>hive.server2.thrift.port</name> <value>10000</value> </property>
- 启动hiveserver2
nohup bin/hive --service hiveserver2 &
- 启动
beeline
客户端
bin/beeline -u jdbc:hive2://hadoop102:10000 -n atguigu
-
metastore
服务
Hive
的``metastore服务的作用是为
Hive CLI或者
Hiveserver2`提供元数据访问接口。
-
metastore运行模式
- metastore有两种运行模式,分别为嵌入式模式和独立服务模式
- 嵌入式模式::在内嵌模式下,Metastore 服务运行在 HiveServer2 进程中。客户端可以直接连接到 HiveServer2 来访问和管理元数据。这种模式适用于小型集群和测试环境。
- 独立服务模式:在远程模式下,Metastore 服务运行在独立的进程中。客户端需要连接到 Metastore 服务所在的主机和端口来访问和管理元数据。这种模式适用于大型集群和生产环境。
-
配置嵌入式模式
<!-- jdbc连接的URL --> <property> <name>javax.jdo.option.ConnectionURL</name> <value>jdbc:mysql://hadoop102:3306/metastore?useSSL=false</value> </property> <!-- jdbc连接的Driver--> <property> <name>javax.jdo.option.ConnectionDriverName</name> <value>com.mysql.jdbc.Driver</value> </property> <!-- jdbc连接的username--> <property> <name>javax.jdo.option.ConnectionUserName</name> <value>root</value> </property> <!-- jdbc连接的password --> <property> <name>javax.jdo.option.ConnectionPassword</name> <value>123456</value> </property>
-
独立服务模式
<!-- jdbc连接的URL --> <property> <name>javax.jdo.option.ConnectionURL</name> <value>jdbc:mysql://hadoop102:3306/metastore?useSSL=false</value> </property> <!-- jdbc连接的Driver--> <property> <name>javax.jdo.option.ConnectionDriverName</name> <value>com.mysql.jdbc.Driver</value> </property> <!-- jdbc连接的username--> <property> <name>javax.jdo.option.ConnectionUserName</name> <value>root</value> </property> <!-- jdbc连接的password --> <property> <name>javax.jdo.option.ConnectionPassword</name> <value>123456</value> </property> <!-- 指定metastore服务的地址 --> <property> <name>hive.metastore.uris</name> <value>thrift://hadoop102:9083</value> </property>
- 启动
metastore
hive --service metastore
- 启动
hiveserver2
hive --service hiveserver2
- 启动
编写 Hive
启动脚本
#!/bin/bash
HIVE_LOG_DIR=$HIVE_HOME/logs
if [ ! -d $HIVE_LOG_DIR ]
then
mkdir -p $HIVE_LOG_DIR
fi
#检查进程是否运行正常,参数1为进程名,参数2为进程端口
function check_process()
{
pid=$(ps -ef 2>/dev/null | grep -v grep | grep -i $1 | awk '{print $2}')
ppid=$(netstat -nltp 2>/dev/null | grep $2 | awk '{print $7}' | cut -d '/' -f 1)
echo $pid
[[ "$pid" =~ "$ppid" ]] && [ "$ppid" ] && return 0 || return 1
}
function hive_start()
{
metapid=$(check_process HiveMetastore 9083)
cmd="nohup hive --service metastore >$HIVE_LOG_DIR/metastore.log 2>&1 &"
[ -z "$metapid" ] && eval $cmd || echo "Metastroe服务已启动"
server2pid=$(check_process HiveServer2 10000)
cmd="nohup hive --service hiveserver2 >$HIVE_LOG_DIR/hiveServer2.log 2>&1 &"
[ -z "$server2pid" ] && eval $cmd || echo "HiveServer2服务已启动"
}
function hive_stop()
{
metapid=$(check_process HiveMetastore 9083)
[ "$metapid" ] && kill $metapid || echo "Metastore服务未启动"
server2pid=$(check_process HiveServer2 10000)
[ "$server2pid" ] && kill $server2pid || echo "HiveServer2服务未启动"
}
case $1 in
"start")
hive_start
;;
"stop")
hive_stop
;;
"restart")
hive_stop
sleep 2
hive_start
;;
"status")
check_process HiveMetastore 9083 >/dev/null && echo "Metastore服务运行正常" || echo "Metastore服务运行异常"
check_process HiveServer2 10000 >/dev/null && echo "HiveServer2服务运行正常" || echo "HiveServer2服务运行异常"
;;
*)
echo Invalid Args!
echo 'Usage: '$(basename $0)' start|stop|restart|status'
;;
esac
- tips
- netstat -nltp
netstat
:用于在 Linux 系统中显示网络连接、路由表和网络接口信息-n
:表示以数字形式显示地址和端口号,而不是使用主机名和服务名-l
:表示仅显示监听套接字-t
:选项表示仅显示 TCP 连接-p
:表示显示每个套接字所属的进程 ID 和名称
function check_process()
方法:该函数接受两个参数,第一个参数是程序名字,第二个参数是监听的端口号。返回程序的pid,同时返回状态代码:0是执行成功,1是不成功。用于判断程序状态有没有异常
- netstat -nltp
hiveserver2
常用交互命令
beeline -u jdbc:hive2://hadoop102:10000 -n atguigu --help
Hive
常见属性配置
Hive
客户端显示当前库和表头,修改``hive-site.xml`
<!--Hive客户端显示当前库和表头,hive-site.xml-->
<property>
<name>hive.cli.print.header</name>
<value>true</value>
<description>Whether to print the names of the columns in query output.</description>
</property>
<property>
<name>hive.cli.print.current.db</name>
<value>true</value>
<description>Whether to include the current database in the Hive prompt.</description>
</property>
Hive
的``log默认存放路径,修改
hive-log4j2.properties`
property.hive.log.dir = ${sys:java.io.tmpdir}/${sys:user.name}
property.hive.log.file = hive.log
Hive
的``JVM`堆内存设置- 新版本的Hive启动的时候,默认申请的
JVM
堆内存大小为256M
,JVM
堆内存申请的太小,导致后期开启本地模式,执行复杂的SQL
时经常会报错:java.lang.OutOfMemoryError: Java heap space
,因此最好提前调整一下HADOOP_HEAPSIZE
这个参数。
- 新版本的Hive启动的时候,默认申请的
export HADOOP_HEAPSIZE=2048
DDL(Data Definition Language)
数据定义
数据库
建表语法
CREATE DATABASE [IF NOT EXISTS] database_name
[COMMENT database_comment]
[LOCATION hdfs_path]
[WITH DBPROPERTIES (property_name=property_value, ...)];
查询数据库
DESCRIBE DATABASE [EXTENDED] db_name;
修改数据库
--修改dbproperties
ALTER DATABASE database_name SET DBPROPERTIES (property_name=property_value, ...);
--修改location
ALTER DATABASE database_name SET LOCATION hdfs_path;
--修改owner user
ALTER DATABASE database_name SET OWNER USER user_name;
删除数据库
DROP DATABASE [IF EXISTS] database_name [RESTRICT|CASCADE];
RESTRICT:严格模式,若数据库不为空,则会删除失败,默认为该模式。
CASCADE:级联模式,若数据库不为空,则会将库中的表一并删除。
切换当前数据库
USE database_name;
表(table
)
创建表
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]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]
[TBLPROPERTIES (property_name=property_value, ...)]
-
关键字说明
- TEMPORARY
- 临时表,该表只在当前会话可见,会话结束,表会被删除。
EXTERNAL
(重点)- 外部表,与之相对应的是内部表(管理表)。管理表意味着Hive会完全接管该表,包括元数据和HDFS中的数据。而外部表则意味着Hive只接管元数据,而不完全接管HDFS中的数据。
- TEMPORARY
data_type
(重点)
Hive | 说明 | 定义 |
---|---|---|
tinyint | 1byte 有符号整数 | |
smallint | 2byte 有符号整数 | |
int | 4byte 有符号整数 | |
bigint | 8byte 有符号整数 | |
boolean | 布尔类型,true 或者false | |
float | 单精度浮点数 | |
double | 双精度浮点数 | |
decimal | 十进制精准数字类型 | decimal(16,2) |
varchar | 字符序列,需指定最大长度,最大长度的范围是[1,65535] | varchar(32) |
string | 字符串,无需指定最大长度 | |
timestamp | 时间类型 | |
binary | 二进制数据 |
类型 | 说明 | 定义 | 取值 |
---|---|---|---|
array | 数组是一组相同类型的值的集合 | array | arr[0] |
map | map是一组相同类型的键-值对集合 | map<string, int> | map['key'] |
struct | 结构体由多个属性组成,每个属性都有自己的属性名和数据类型 | struct<id:int, name:string> | struct.id |
-
类型转换
-
隐式转换
- 任何整数类型都可以隐式地转换为一个范围更广的类型
- 所有整数类型、float和string类型都可以隐式地转换成
double
tinyint
、smallint
、int
都可以转换为float
boolean
类型不可以转换为任何其它的类型
-
显示转换
- 借助cast函数完成显示的类型转换
-
PARTITIONED BY
- 创建分区表
-
CLUSTERED BY ... SORTED BY...INTO ... BUCKETS
- 创建分桶表
-
ROW FORMAT
(重点)- 指定SERDE,SERDE是Serializer and Deserializer的简写。Hive使用SERDE序列化和反序列化每行数据。
ROW FORAMT DELIMITED [FIELDS TERMINATED BY char] [COLLECTION ITEMS TERMINATED BY char] [MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char] [NULL DEFINED AS char]
-
fields terminated by
:列分隔符 -
collection items terminated by
:map
、struct
和array
中每个元素之间的分隔符 -
collection items terminated by
:map
、struct
和array
中每个元素之间的分隔符 -
lines terminated by
:行分隔符 -
SERDE
关键字可用于指定其他内置的SERDE
或者用户自定义的SERDE
。例如JSON SERDE
,可用于处理JSON
字符串ROW FORMAT SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value,property_name=property_value, ...)]
-
STORED AS
(重点)- 指定文件格式,常用的文件格式有,textfile(默认值),sequence file,orc file、parquet file等等。
-
TBLPROPERTIES
- 用于配置表的一些
KV
键值对参数
- 用于配置表的一些
-
Create Table As Select
(CTAS
)建表- 该语法允许用户利用select查询语句返回的结果,直接建表,表的结构和查询语句的结构保持一致,且保证包含select查询语句放回的内容。不包含分区表
-
Create Table Like
语法- 该语法允许用户复刻一张已经存在的表结构,与上述的CTAS语法不同,该语法创建出来的表中不包含数据。
-
查看表
- 展示所有表
SHOW TABLES [IN database_name] LIKE ['identifier_with_wildcards'];
- 查看表信息
DESCRIBE [EXTENDED | FORMATTED] [db_name.]table_name
修改表
- 重命名表
ALTER TABLE table_name RENAME TO new_table_name
- 增加列
ALTER TABLE table_name ADD COLUMNS (col_name data_type [COMMENT col_comment], ...)
- 更新列
ALTER TABLE table_name CHANGE [COLUMN] col_old_name col_new_name column_type [COMMENT col_comment] [FIRST|AFTER column_name]
- 替换列
ALTER TABLE table_name REPLACE COLUMNS (col_name data_type [COMMENT col_comment], ...)
删除表
DROP TABLE [IF EXISTS] table_name;
清空表
TRUNCATE [TABLE] table_name
- 注意:truncate只能清空管理表,不能删除外部表中数据。
DML(Data Manipulation Language)
数据操作
Load
- Load语句可将文件导入到Hive表中。
LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)];
- 关键字说明:
- local:表示从本地加载数据到Hive表;否则从HDFS加载数据到Hive表。
- overwrite:表示覆盖表中已有数据,否则表示追加。
- partition:表示上传到指定分区,若目标是分区表,需指定分区。
Insert
INSERT (INTO | OVERWRITE) TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement;
- 关键字说明:
- INTO:将结果追加到目标表
- OVERWRITE:用结果覆盖原有数据
将查询结果写入目标路径
INSERT OVERWRITE [LOCAL] DIRECTORY directory
[ROW FORMAT row_format] [STORED AS file_format] select_statement;
Export
&Import
- Export导出语句可将表的数据和元数据信息一并到处的HDFS路径,Import可将Export导出的内容导入Hive,表的数据和元数据信息都会恢复。Export和Import可用于两个Hive实例之间的数据迁移。