一、Hive
1.1 数据仓库
1.1.1 数据库与数据仓库
1)数据库是面向事务设计,数据仓库是面向主题设计的;
2)数据库一般存储了业务数据,数据仓库一般存储的是历史数据;
3)数据库设计应该尽量避免冗余,一般针对某一业务应用进行设计;数据仓库在设计时会有意地引入冗余,依照分析需求、分析维度、分析指标进行设计;
4)数据库是为了捕获数据而设计,数据仓库是为了分析数据而设计;
数据仓库是在数据库已经大量存在的情况下,为了进一步挖掘数据资源,以供数据用户决策使用而产生的。
1.1.2 数据仓库的分层架构
从架构图看出,最下层是数据源,数据仓库中的数据一般来源于不同的数据源,它可以是文档文件,也可以是数据库。中间层是我们的数据仓库,最上层是数据应用层。可以看出,数据是自下而上地流入数据仓库后,为上层应用提供数据的支持。可以这样理解,数据仓库只是一个中间集成化数据管理的平台。
数据仓库从各数据源获取数据,以及在数据仓库内的数据转换和流动都可以认为是ETL(抽取Extra, 转化Transfer, 装载Load)的过程。ETL是数据仓库的流水线,也可以认为是数据仓库的血液,它维系着数据仓库中数据的新陈代谢,而数据仓库日常的管理和维护工作的大部分精力就是保持ETL的正常和稳定。
1.1.3 数据仓库的元数据管理
元数据主要记录了数据仓库中模型的定义、各层级之间的映射关系,监控数据仓库的数据状态,以及ETL的任务运行状态等。一般会通过元数据资料库进行统一存储和管理。
元数据是数据仓库管理系统的重要组成部分,元数据管理贯穿数据仓库构建的整个过程,直接影响着数据仓库的构建、使用和维护。
它的主要作用:
- 它定义了源数据系统到数据仓库的映射、数据转换的规则、数据仓库的逻辑结构、数据更新的规则、数据导入历史记录以及装载周期等相关内容;
- 用户在使用数据仓库时,通过元数据访问数据,明确数据项的含义以及定制报表;
- 数据仓库的规模及其复杂性离不开正确的元数据管理,包括增加或移除外部数据源,改变数据清洗方法,控制出错的查询以及安排备份等;
元数据可分为技术元数据和业务元数据。技术元数据为开发和管理数据仓库的 IT 人员使用,它描述了与数据仓库开发、管理和维护相关的数据,包括数据源信息、数据转换描述、数据仓库模型、数据清洗与更新规则、数据映射和访问权限等。而业务元数据为管理层和业务分析人员服务,从业务角度描述数据,包括商务术语、数据仓库中有什么数据、数据的位置和数据的可用性等,帮助数据用户更好地理解数据仓库中哪些数据是可用的以及如何使用。
由此可见,元数据不仅定义了数据仓库中数据的模式、来源、抽取和转换规则等,而且是整个数据仓库系统运行的基础,元数据把数据仓库系统中各个松散的组件联系起来,组成了一个有机的整体。
1.2 Hive介绍
1.2.1 Hive的基本概念
Hive是基于Hadoop的一个数据仓库工具,主要用于数据的提取、转换、加载。Hive能够将结构化数据文件映射成一张数据表,并提供SQL查询功能,能将SQL语句转化成MapReduce任务进行运算,底层由HDFS来提供数据的存储。
1.2.2 Hive的基本架构
- 用户接口:包括CLI、JDBC/ODBC、WebGUI。其中,CLI为shell命令行,JDBC/ODBC是Hive的JAVA实现,WebGUI是通过浏览器访问Hive。
- 元数据存储:通常是存储在关系数据库如mysql/derby中。Hive 将元数据存储在数据库中。Hive中的元数据包括表信息,列的信息,分区信息,表的数据所在目录等。
- 解释器、编译器、优化器、执行器:完成HQL 查询语句从词法分析、语法分析、编译、优化以及查询计划的生成。生成的查询计划存储在HDFS 中,并由MapReduce调用执行。
1.2.3 Hive与传统数据库的关系
Hive | RDBMS | |
---|---|---|
查询语言 | HQL | SQL |
数据存储 | HDFS | Raw Device or Local FS |
执行 | MapReduce | Executor |
数据延迟 | 高 | 低 |
数据规模 | 大 | 小 |
应用场景 | 数据统计分析 | 数据持久化存储 |
1.3 Hive安装
- 第一步:下载压缩包,并解压;
cd /export/softwares/
tar -zxvf apache-hive-3.1.0-bin.tar.gz -C ../servers/
- 第二步:修改hive配置文件;
cd /export/servers/apache-hive-3.1.0-bin/conf
cp hive-env.sh.template hive-env.sh
# 配置HADOOP_HOME
HADOOP_HOME=/export/servers/hadoop-3.1.1
# Hive配置文件路径
export HIVE_CONF_DIR=/export/servers/apache-hive-3.1.0-bin/conf
hive-site.xml:
cd /export/servers/apache-hive-3.1.0-bin/conf
vim hive-site.xml
配置文件内容:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123456</value>
</property>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://node03:3306/hive?createDatabaseIfNotExist=true&useSSL=false</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<property>
<name>hive.metastore.schema.verification</name>
<value>false</value>
</property>
<property>
<name>datanucleus.schema.autoCreateAll</name>
<value>true</value>
</property>
<property>
<name>hive.server2.thrift.bind.host</name>
<value>node03.hadoop.com</value>
</property>
</configuration>
- 第三步:配置hive的环境变量;
# 修改配置文件
sudo vim /etc/profile
export HIVE_HOME=/export/servers/apache-hive-3.1.0-bin
export PATH=:$HIVE_HOME/bin:$PATH
- 第四步:在node03安装mysql,并启动mysql服务;
# 安装mysql相关包
yum install mariadb mariadb-server
# 启动mysql服务
systemctl start mariadb
# 设置用户名和密码
mysql_secure_installation
# 给用户授权
grant all privileges on *.* to 'root'@'%' identified by 'root' with grant option;
flush privileges;
-
第五步:将mysql驱动包添加到hive的lib目录下;
-
第六步:启动hadoop服务,然后再执行
hive
命令。如果出现hive>
提示符,代表安装成功(如下图);
1.4 Hive的基本操作
1.4.1 数据库操作
- 创建数据库
create database [if not exists] 数据库名;
- 创建数据库并指定存储位置
create database 数据库名 location 存储路径;
例如:
create database myhive location '/myhive';
hive默认存储位置由hive-site.xmlp配置文件的hive.metastore.warehouse.dir
参数来指定。
- 修改数据库
hive只能修改数据库的一些基本属性,不能够修改元数据信息(比如数据库名称、数据库所在位置等)。
alter database 数据库名 set dbproperties('参数名'='属性值');
- 查看数据库的详细信息
desc database [extended] 数据库名;
如果指定了extended参数,那么就会显示数据库的详细信息。
- 删除数据库
drop database 数据库名 [cascade];
如果数据库不为空,那么需要指定cascade参数。
1.4.2 表操作
1.4.2.1 创建表的基本语法
创建表的基本语法:
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:代表创建一个外部表。在创建外部表时需要通过LOCATION指定数据的实际存放路径。所以删除外部表的时候,只会删除表的元数据,不删除数据。如果没有指定EXTERNAL,默认就是内部表。当删除内部表的时候,内部表的元数据和数据会被一起删除。
- ROW FORMAT:设置数据格式。用户在建表的时候可以自定义 SerDe 或者使用自带的 SerDe。如果没有指定 ROW FORMAT 或者 ROW FORMAT DELIMITED,将会使用自带的SerDe。在建表的时候,用户还需要为表指定列,用户在指定列的同时也可以自定义的 SerDe,Hive通过 SerDe 确定列的数据;
SerDe是Serialize和Deserilize的英文缩写。hive通过序列化和反序列化来完成表的读写操作。序列化操作就是把hive使用的java对象转换成能写入hdfs的字节序列,或者其他系统能识别的流文件。反序列化操作就是把字符串或者二进制流转换成hive能识别的java对象。比如:select语句会用到Serialize对象, 把hdfs数据解析出来;insert语句会使用Deserilize,数据写入hdfs系统,需要把数据序列化。
- STORED AS:文件的存储格式。如果是纯文本,可以使用使用
STORED AS TEXTFILE
;如果数据需要压缩,使用STORED AS SEQUENCEFILE
。hive默认的文件存储格式为TEXTFILE
,可以通过配置hive.default.fileformat
来修改; - CLUSTERED BY:针对某一列进行桶的组织。桶是更为细粒度的数据范围划分。Hive采用对列值哈希,然后除以桶的个数再求余的方式决定该条记录存放在哪个桶当中;
- PARTITIONED BY:创建分区表。指定分区字段的名字不能够表字段名字相同,否则会报错;
1.4.2.2 字段类型
类型 | 描述 | 示例 | 版本限制 |
---|---|---|---|
BOOLEAN | true/false | 1Y | |
TINYINT | 1个字节的有符号整数,-128~127 | 1S | |
SMALLINT | 2个字节的有符号整数,-32768~32767 | 1S | |
INT | 4个字节的有符号整数 | 1 | |
BIGINT | 8个字节的有符号整数 | 1L | |
FLOAT | 4个字节的单精度浮点数 | 1.0 | |
DOUBLE | 8个字节的双精度浮点数 | 1.0 | Hive 2.2.0+ |
DECIMAL | 任意精度的有符号小数 | 1.0 | Hive 0.11.0+开始引入38位小数,Hive0.13.0+开始可以自定义小数位 |
Numeric | 任意精度的有符号小数 | 1.0 | Hive 3.0.0+ |
STRING | 变长字符串 | "a"或’a’ | |
VARCHAR | 变长字符串 | "a"或’a’ | Hive 0.12.0+ |
CHAR | 定长字符串 | "a"或’a’ | Hive 0.13.0+ |
BINARY | 字节数组 | Hive 0.8.0+ | |
TIMESTAMP | 时间戳,毫秒为单位 | 1287897987312 | Hive 0.8.0+ |
DATE | 日期 | ‘2020-06-06’ | Hive 0.12.0+ |
INTERVAL | 时间频率间隔 | Hive 1.2.0+ | |
ARRAY | 数组,只能存储相同类型的数据 | array(1,2,3,4,5) | Hive 0.14+ |
MAP | 存储键值对的集合 | map(‘a’,1,‘b’,2) | Hive 0.14+ |
STRUCT | 结构体,可存储不同类型的数据 | person_struct(1, ‘小白’, 18) | |
UNION | 有限取值范围内的一个值 | hive 0.7.0+ |
具体类型可以参考:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Types
1.4.2.3 创建表操作
use myhive;
# 创建简单表
create table company(id int, name string);
# 创建表并指定分隔符
create table if not exists company (id, name)
row format delimited fields terminated by '\t';
# 根据查询结果创建表
create table t2 as select * from t1; # 复制表结构和数据
create table t2 like t1; # 复制表结构
1.4.4.4 分区表
当表中的数据量非常大的时候,我们可以对一个表的数据进行分区,例如:日期。这样可以提高对数据的查询效率。
- 创建分区表:
# 创建分区表
create table score(s_id string,c_id string, s_score int) partitioned by (year string, month string) row format delimited fields terminated by '\t' location '/score';
上面我们创建了一个分区表score,它按照字段year和month进行分区。month值相同的数据会存放在同一个分区里面。
这里需要强调的是,分区列year和month并不真正存在于数据库表中,它们只是我们人为规定的。Hive不支持将表中的某些列作为分区列。
- 查看分区表目录:
hdfs dfs -ls /score/year=2020&month=6/
- 查看分区:
show partitions score;
- 加载数据到分区表:
load data local inpath '/export/data/score.csv' into table score partition (year='2020',month='6');
-
- 查看分区数据:
select * from score where year = '2020' and month = '6';
查询分区数据的方式指定分区字段作为查询条件。指定分区名之后就不再全表扫描,直接从指定分区中查询,从而提高数据的查询效率。
- 添加分区:
alter table score add partition(year='2020', month='5');
- 删除分区:
alter table score drop partition(year='2020', month='5');
1.4.4.5 分桶表
与分区不同的是,分区依据的不是表里面真实的列,而分桶是依据表里面真实的列,将数据按照指定的字段分到不同的桶里面。
- Hive是如何确定数据分到哪个桶?
Hive是通过对某列值的hash对分桶数取模来决定数据存放在哪个桶。比如说对name属性分为3个桶,那么就是对name属性值的hash对3进行取模,然后按照取模结果对数据分桶存放。如果结果为0则记录在第一个文件,结果为1记录在第二个文件,结果为2记录在第三个文件,以此类推。
如果要使用分桶功能,首先要先开启分桶:
set hive.enforce.bucketing=true;
然后设置Reduce的个数:
set mapreduce.job.reduces = 3;
创建表时候,指定分桶的数量:
# 创建表时指定按照c_id列进行分桶,并且将数据放入到3个分桶中
create table ... clustered by(c_id) into 3 buckets row format delimited fields terminated by '\t';
向分桶表插入数据:
insert overwrite table course select * from course_two cluster by (c_id);
查看分桶数据:
# 查看第一个分桶的数据
select * from course tablesample(bucket 1 out of 3 on c_id);
1.4.4.5 修改的其他操作
- 修改表:
# 重命名
alter table old_table_name rename to new_table_name;
# 查询表结构
desc tablename;
# 添加列
alter table tablename add columns (column_name column_type, ...);
# 删除表
drop table tablename;