目录
[1.1 Hive整体架构](#1.1 Hive整体架构)
[1.2 Hive组件](#1.2 Hive组件)
[1.3 Hive数据模型(Data Model)](#1.3 Hive数据模型(Data Model))
[1.3.1 Databases](#1.3.1 Databases)
[1.3.2 Tables](#1.3.2 Tables)
[1.3.3 Partitions](#1.3.3 Partitions)
[1.3.4 Buckets](#1.3.4 Buckets)
[2.1 SerDe 作用](#2.1 SerDe 作用)
[2.2 Hive读写文件流程](#2.2 Hive读写文件流程)
[2.2.1 读取文件的过程](#2.2.1 读取文件的过程)
[2.2.2 写入文件的过程](#2.2.2 写入文件的过程)
[2.3 SerDe相关语法](#2.3 SerDe相关语法)
[2.3.1 LazySimpleSerDe分隔符指定](#2.3.1 LazySimpleSerDe分隔符指定)
[2.3.2 默认分隔符](#2.3.2 默认分隔符)
[2.4 Hive数据存储路径](#2.4 Hive数据存储路径)
[2.4.1 默认存储路径](#2.4.1 默认存储路径)
[2.4.2 指定存储路径](#2.4.2 指定存储路径)
一、架构及组件介绍
1.1 Hive整体架构
1.2 Hive组件
- 用户接口:Client
- CLI:shell命令行
- JDBC/ODBC:Hive中的Thrift服务器允许外部客户端通过网络与Hive进行交互,类似于JDBC或ODBC协议
- WEBUI:通过浏览器访问Hive
- 元数据:Metastore
元数据通常是存储在关系数据库如 mysql/derby中。Hive 中的元数据包括表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等。
- Hadoop
数据使用 HDFS 进行存储,使用 MapReduce 进行计算。
- 驱动器:Driver
- 解析器(SQL Parser):将 SQL 字符串转换成抽象语法树 AST,这一步一般都用第 三方工具库完成,比如 antlr;对 AST 进行语法分析,比如表是否存在、字段是否存在、SQL 语义是否有误。
- 编译器(Physical Plan):将 AST 编译生成逻辑执行计划。
- 优化器(Query Optimizer):对逻辑执行计划进行优化。
- 执行器(Execution):把逻辑执行计划转换成可以运行的物理计划。当下Hive支持MapReduce、Tez、Spark3种执行引擎
Driver驱动器总结:完成 HQL 查询语句从词法分析、语法分析、编译、优化以及查询计划的生成。生成的查询计划存储在 HDFS 中,随后执行引擎调用执行。当下Hive支持MapReduce、Tez、Spark3种执行引擎。
1.3 Hive数据模型(Data Model)
模型用来描述数据,组织数据和对数据进行操作。
Hive的数据模型类似于RDMS库表结构,此外它还有自己特有的模型。Hive中的数据可以在粒度级别分为三类:Table类、Partition分区、Bucket分桶。
1.3.1 Databases
Hive的数据存储在HDFS上的,默认有一个根目录 ,在hive-site.xml配置文件中,由参数hive.metastore.warehouse.dir指定。默认值为/user/hive/warehouse。
Hive中的数据库 在HDFS上的存储路径为 :${hive.metastore.warehouse.dir}/databasename.db
比如,名为test的数据库 存储路径为**:/user/hive/warehouse/test.db**
1.3.2 Tables
Hive表与关系数据库中的表相同,Hive中的表所对应的数据是存储在Hadoop的文件系统中,而表相关的元数据是存储在RDBMS中。Hive有两种类型的表,分别是Managed Table内部表、External Table外部表。创建表时,默是内部表。
Hive中的表 的数据在HDFS上的存储路径为 :${hive.metastore.warehouse.dir}/databasename.db/tablename
比如,test的数据库下t_user表 存储路径为:/user/hive/warehouse/test.db/t_user
1.3.3 Partitions
Partition分区表是hive的一种优化手段表,当Hive表数据量大,查询时通过 where子句筛选指定的分区,这样的查询效率会提高很多,避免 全表扫描。
Hive支持根据指定的字段进行分区,分区的字段可以是日期、地域、种类等具有标识意义的字段。分区在存储层面上的表现是table表目录下以子文件夹形式存在 。一个文件夹表示一个分区。子文件命名标准:分区列=分区值,Hive还支持分区下继续创建分区,所谓的多重分区。
1.3.4 Buckets
Bucket分桶表是hive的一种优化手段表。分桶是指数据表中某字段的值,经过hash计算规则将数据分为指定的若干小文件。Bucket分桶表 在hdfs中表现为同一个表目录下的数据根据hash散列之后变成多个文件 。分区针对的是数据的存储路径;分桶针对的是数据文件(数据粒度更细)。
分桶默认规则 是:分桶编号 Bucket number = hash_function(分桶字段) % 桶数量。桶编号相同的数据会被分到同一个桶当中。
ps:hash_function函数 取决于分桶字段的数据类型 ,如果是int类型 ,hash_function(int) == int; 如果是其他数据类型,比如bigint,string或者复杂数据类型 ,hash_function比较棘手,将是从该类型派生的某个数字,比如hashcode值。
二、Hive读写文件机制
2.1 SerDe 作用
SerDe是Serializer、Deserializer的简称,目的是用于序列化和反序列化 。序列化是对象转化为字节码 的过程(写);而**反序列化是字节码转换为对象(读)**的过程。
sql
# 读过程:反序列化
HDFS files --> InputFileFormat --> <key,value> --> Deserializer(反序列化) --> Row Object
# 写过程: 序列化
Row Object --> serializer(序列化) --> <key,value> --> OutputFileFormat --> HDFS files
通过desc formatted tablename 查看表的相关SerDe信息,SerDe默认:org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe
例如以t_order 为例:
sql
---建表
CREATE TABLE t_order (
oid int ,
uid int ,
otime string,
oamount int
)
ROW format delimited FIELDS TERMINATED BY ",";
---插入数据
load data local inpath "/opt/module/hive_data/t_order.txt" into table t_order;
#== 查看t_order表的详细信息
desc formatted t_order;
2.2 Hive读写文件流程
2.2.1 读取文件的过程
- 流程:
HDFS files --> InputFileFormat --> <key,value> --> Deserializer(反序列化) --> Row Object
- 机制:
首先调用InputFormat(默认TextInputFormat)进行一行一行的读取,返回kv键值对记录(默认是一行对应一条记录)。然后调用SerDe(默认LazySimpleSerDe)的Deserializer,将一条记录中的value根据分隔符切分为各个字段。
2.2.2 写入文件的过程
- 流程:
Row Object --> serializer(序列化) --> <key,value> --> OutputFileFormat --> HDFS files
- 机制:
将Row写入文件时,首先调用SerDe(默认LazySimpleSerDe)的Serializer将对象转换成字节序列。然后调用OutputFormat将数据写入HDFS文件中。
2.3 SerDe相关语法
SerDe语法指路:
LanguageManual DDL - Apache Hive - Apache Software Foundationhttps://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-RowFormats&SerDe在Hive建表语句中,和SerDe相关的语法:
- hive的建表语法
sql
# 建表语句
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]
[TBLPROPERTIES (property_name=property_value, ...)]
[AS select_statement]
- 字段解释说明
(1) CREATE TABLE 创建一个指定名字的表。如果相同名字的表已经存在,则抛出异常;
用户可以用 IF NOT EXISTS 选项来忽略这个异常。
(2) EXTERNAL 关键字可以让用户创建一个外部表,在建表的同时可以指定一个指向实
际数据的路径( LOCATION ), 在删除表的时候,内部表的元数据和数据会被一起删除,而外
部表只删除元数据,不删除数据 。
(3) COMMENT :为表和列添加注释。
(4) PARTITIONED BY 创建分区表
(5) CLUSTERED BY 创建分桶表
(6) SORTED BY 不常用,对桶中的一个或多个列另外排序
(7) ROW FORMAT:ROW FORMAT是语法关键字,以下的DELIMITED和SERDE二选其一。
- DELIMITED[FIELDS TERMINATED BY char]
[COLLECTION ITEMS TERMINATED BY char]
[MAP KEYS TERMINATED BY char]
[LINES TERMINATED BY char]
- SERDEserde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)]
用户在建表的时候可以自定义 SerDe 或者使用自带的 SerDe 。如果没有指定 ROW
FORMAT 或者 ROW FORMAT DELIMITED ,将会使用自带的 SerDe 。
在建表的时候,用户还需要为表指定列,用户在指定表的列的同时也会指定自定义的 SerDe , Hive 通过 SerDe 确定表 的具体的列的数据。
SerDe 是 Serialize/Deserilize 的简称, hive 使用 Serde 进行行对象的序列与反序列化。
(8) STORED AS :指定存储文件类型常用的存储文件类型:SEQUENCEFILE (二进制序列文件)、 TEXTFILE (文本)、 RCFILE (列式存储格式文件).如果文件数据是纯文本,可以使用STORED AS TEXTFILE 。如果数据需要压缩,使用 STORED AS SEQUENCEFILE。
(9) LOCATION :指定表在 HDFS 上的存储位置。
(10) AS:后跟查询语句,根据查询结果创建表。
(11) LIKE 允许用户复制现有的表结构,但是不复制数据。
sql
#==== 例如:支付表的建表语句
DROP TABLE IF EXISTS ods_payment_info_inc;
CREATE EXTERNAL TABLE ods_payment_info_inc
(
`type` STRING COMMENT '变动类型',
`ts` BIGINT COMMENT '变动时间',
`data` STRUCT<id :STRING,out_trade_no :STRING,order_id :STRING,user_id :STRING,payment_type :STRING,trade_no
:STRING,total_amount :DECIMAL(16, 2),subject :STRING,payment_status :STRING,create_time :STRING,callback_time
:STRING,callback_content :STRING> COMMENT '数据',
`old` MAP<STRING,STRING> COMMENT '旧值'
) COMMENT '支付表'
PARTITIONED BY (`dt` STRING)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.JsonSerDe'
LOCATION '/warehouse/gmall/ods/ods_payment_info_inc/';
2.3.1 LazySimpleSerDe分隔符指定
LazySimpleSerDe是Hive默认的序列化类,包含4种子语法,分别用于指定字段之间、集合元素之间、map映射 kv之间、换行的分隔符号。在建表的时候可以根据数据的特点灵活搭配使用。
sql
DELIMITED [FIELDS TERMINATED BY char] --- 字段之间的分隔符
[COLLECTION ITEMS TERMINATED BY char] --- 集群元素之间的分隔符
[MAP KEYS TERMINATED BY char] --- map映射kv之间的分隔符
[LINES TERMINATED BY char] --- 行数据之间的分隔符
2.3.2 默认分隔符
hive建表时如果没有row format语法。此时字段之间默认的分割符是'\001'
2.4 Hive数据存储路径
2.4.1 默认存储路径
Hive表 默认存储路径是由 ${HIVE_HOME}/conf/hive-site.xml配置文件的hive.metastore.warehouse.dir属性指定,默认值是:/user/hive/warehouse。在该路径下,文件将根据所属的库、表,有规律的存储在对应的文件夹下。
2.4.2 指定存储路径
在Hive建表的时候,可以通过location语法来更改数据在HDFS上的存储路径,使得建表加载数据更加灵活方便,语法为:LOCATION '<hdfs_location>'
sql
# 建表语句
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] # ===指定表在 HDFS 上的存储位置。
[TBLPROPERTIES (property_name=property_value, ...)]
[AS select_statement]
sql
# ====例如:退单表的建表语句
DROP TABLE IF EXISTS ods_order_refund_info_inc;
CREATE EXTERNAL TABLE ods_order_refund_info_inc
(
`type` STRING COMMENT '变动类型',
`ts` BIGINT COMMENT '变动时间',
`data` STRUCT<id :STRING,user_id :STRING,order_id :STRING,sku_id :STRING,refund_type :STRING,refund_num :BIGINT,refund_amount
:DECIMAL(16, 2),refund_reason_type :STRING,refund_reason_txt :STRING,refund_status :STRING,create_time
:STRING> COMMENT '数据',
`old` MAP<STRING,STRING> COMMENT '旧值'
) COMMENT '退单表'
PARTITIONED BY (`dt` STRING)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.JsonSerDe' --指定serDE
LOCATION '/warehouse/gmall/ods/ods_order_refund_info_inc/'; -- 指定在hdfs上存储位置