Hive简介
Hive是基于Hadoop的一个数据仓库工具,能够将结构化的数据文件映射为数据库表,并提供类SQL查询功能。其本质是将SQL转换为MapReduce或Spark任务进行运算,底层依赖HDFS提供数据存储。从某种意义上来说,Hive可以被理解为一个将SQL转换为MapReduce/Spark任务的工具。
Hive的特点:
- 简单易用,提供了类似SQL的查询语言(HQL),使得精通SQL但不熟悉Java编程的人员也能轻松上手,高效地进行大数据分析。
- 高度灵活,支持用户自定义函数(UDF)和自定义存储格式,能够满足多样化的业务需求。
- 强大的扩展性,专为超大数据集设计,集群扩展简单,能够轻松应对海量数据的存储和计算需求。
- 统一的元数据管理,元数据可与Presto、Impala、SparkSQL等工具共享,便于数据的统一管理和跨工具查询。
- 执行延迟较高,Hive的计算模式决定了其执行延迟相对较高,不适合用于数据的实时处理,但非常适用于海量数据的离线处理场景。
使用Hive的主要原因包括以下几点:
- 降低开发成本:学习MapReduce的成本较高,且项目周期通常较短,MapReduce实现复杂查询逻辑的开发难度较大,而Hive采用类似SQL的操作接口,能够快速开发,避免书写MapReduce,减少学习成本,同时提供功能扩展。
- 提高开发效率:Hive的类SQL语法使得数据处理更加直观,开发人员可以快速上手,减少开发时间,提升开发效率。
Hive架构
- CLI & Thrift & WebGU:
- CLI,通过Hive命令行的的方式来操作数据
- Thrift/JDBC,通过Thrift协议按照标准的JDBC的方式操作数据
- WebGUI,通过浏览器访问Hive
- Metastore:
在Hive中,表名、表结构、字段名、字段类型、表的分隔符等统一被称为元数据。所有的元数据默认存储在Hive内置的Derby数据库中,但由于Derby只能有一个实例,也就是说不能有多个命令行客户端同时访问,所以在实际生产环境中,通常使用MySQL代替Derby。
Hive进行的是统一的元数据管理,即在Hive上创建了一张表,在Presto/Impala/SparkSQL中都是可以直接使用的,它们会从Metastore中获取统一的元数据信息;同样的,在Presto/Impala/SparkSQL中创建一张表,在Hive中也可以直接使用。
- Hive在执行一条HQL的时候,会经过以下步骤:
- 语法解析:Antlr定义SQL的语法规则,完成SQL词法,语法解析,将SQL转化为抽象语法树ASTTree
- 语义解析:遍历ASTTree,抽象出查询的基本组成单元QueryBlock
- 生成逻辑执行计划:遍历QueryBlock,翻译为执行操作树OperatorTree
- 优化逻辑执行计划:逻辑层优化器进行OperatorTree变换,合并不必要的ReduceSinkOperator,减少shuffle数据量
- 生成物理执行计划:遍历OperatorTree,翻译为MapReduce任务
- 优化物理执行计划:物理层优化器进行MapReduce任务的变换,生成最终的执行计划
数据类型
基本数据类型
Hive支持的主要基本数据类型如下:
大类 | 类型 |
---|---|
Integers(整型) | TINYINT - 1字节的有符号整数 SMALLINT - 2字节的有符号整数 INT - 4字节的有符号整数 BIGINT - 8字节的有符号整数 |
Boolean(布尔型) | BOOLEAN - TRUE/FALSE |
Floating point numbers(浮点型) | FLOAT - 单精度浮点型 DOUBLE - 双精度浮点型 |
Fixed point numbers(定点数) | DECIMAL - 用户自定义精度定点数,比如DECIMAL(7,2) |
String types(字符串) | STRING - 指定字符集的字符序列 VARCHAR - 具有最大长度限制的字符序列 CHAR - 固定长度的字符序列 |
Date and time types(日期时间类型) | TIMESTAMP - 时间戳 TIMESTAMP WITH LOCAL TIME ZONE - 时间戳,纳秒精度 DATE - 日期类型 |
Binary types(二进制类型) | BINARY - 字节序列 |
TIMESTAMP和TIMESTAMP WITH LOCAL TIME ZONE的区别如下:
- TIMESTAMP:提交什么时间就保存什么时间,查询时也不做任何转换
- TIMESTAMP WITH LOCAL TIME ZONE:用户提交时间给数据库时,会被转换成数据库所在的时区来保存;查询时则按照查询客户端的不同,转换为查询客户端所在时区的时间
隐式转换
Hive中基本数据类型遵循以下的层次结构,按照这个层次结构,子类型到祖先类型允许隐式转换,例如INT类型的数据允许隐式转换为BIGINT类型。额外需要注意的是,按照类型层次结构允许将STRING类型隐式转换为DOUBLE类型。
复杂类型
类型 | 描述 | 示例 |
---|---|---|
STRUCT | 类似于对象,是字段的集合,字段的类型可以不同,可以使用名称.字段名方式进行访问 | STRUCT (‘xiaoming’, 12 , ‘2018-12-12’) |
MAP | 键值对的集合,可以使用名称[key]的方式访问对应的值 | map(‘a’, 1, ‘b’, 2) |
ARRAY | 数组是一组具有相同类型和名称的变量的集合,可以使用名称[index]访问对应的值 | ARRAY(‘a’, ‘b’, ‘c’, ‘d’) |
示例
如下是一个基本数据类型和复杂数据类型的使用示例:
1 | CREATE TABLE employees ( |
内容格式
当数据存储在文本文件中,必须按照一定格式区别行和列,如使用逗号作为分隔符的CSV文件或者使用制表符作为分隔值的TSV文件。但此时也存在一个缺点,就是正常的文件内容中也可能出现逗号或者制表符。因此,Hive默认使用了几个平时很少出现的字符,这些字符一般不会作为内容出现在文件中。Hive默认的行和列分隔符如下表所示:
分隔符 | 描述 |
---|---|
\n | 对于文本文件来说,每行是一条记录,所以可以使用换行符来分割记录 |
^A (Ctrl+A) | 分割字段 (列),在CREATE TABLE语句中也可以使用八进制编码\001来表示 |
^B | 用于分割ARRAY或者STRUCT中的元素,或者用于MAP中键值对之间的分割,在CREATE TABLE语句中也可以使用八进制编码\002表示 |
^C | 用于MAP中键和值之间的分割,在CREATE TABLE语句中也可以使用八进制编码\003表示 |
存储格式
Hive会在HDFS为每个数据库上创建一个目录,数据库中的表是该目录的子目录,表中的数据会以文件的形式存储在对应的表目录下。Hive支持以下几种文件存储格式:
格式 | 说明 |
---|---|
TextFile | 存储为纯文本文件,这是Hive默认的文件存储格式,这种存储方式数据不做压缩,磁盘开销大,数据解析开销大 |
SequenceFile | SequenceFile是Hadoop API提供的一种二进制文件,它将数据以<key,value>的形式序列化到文件中,这种二进制文件内部使用Hadoop的标准的Writable接口实现序列化和反序列化,它与Hadoop API中的MapFile是互相兼容的;Hive中的SequenceFile继承自Hadoop API的SequenceFile,不过它的key为空,使用value存放实际的值,这样是为了避免MR在运行map阶段进行额外的排序操作 |
RCFile | RCFile文件格式是FaceBook开源的一种Hive的文件存储格式,首先将表分为几个行组,对每个行组内的数据按列存储,每一列的数据都是分开存储 |
ORC Files | ORC是在一定程度上扩展了RCFile,是对RCFile的优化 |
Avro Files | Avro是一个数据序列化系统,设计用于支持大批量数据交换的应用,它的主要特点有:支持二进制序列化方式,可以便捷,快速地处理大量数据;动态语言友好,Avro提供的机制使动态语言可以方便地处理Avro数据 |
Parquet | Parquet是基于Dremel的数据模型和算法实现的,面向分析型业务的列式存储格式,它通过按列进行高效压缩和特殊的编码技术,从而在降低存储空间的同时提高了IO效率 |
存储格式通常在创建表的时候使用STORED AS参数指定:
1 | CREATE TABLE page_view(viewTime INT, userid BIGINT) |
各个存储文件类型指定方式如下:
1 | STORED AS TEXTFILE |
数据模型
Hive提供了多种数据模型(表类型),以满足不同的数据存储和处理需求。主要的表类型包括:内部表(Managed Table)、外部表(External Table)、分区表(Partitioned Table)和桶表(Bucketed Table)。
内部表
定义:内部表是Hive默认的表类型。当创建内部表时,Hive会将数据移动到Hive的默认存储位置(通常是HDFS的某个目录)。
特点:
- 数据存储在Hive的默认目录下(例如/user/hive/warehouse)
- 删除表时,表的元数据和数据都会被删除
- 适合存储完全由Hive管理的数据
使用场景:适用于数据完全由Hive管理,且不需要与其他系统共享数据的场景。
1 | CREATE TABLE managed_table ( |
外部表
定义:外部表允许Hive引用存储在其他位置的数据(例如HDFS的其他目录或外部存储系统)。创建外部表时,Hive不会移动数据,而是直接引用数据所在的路径。
特点:
- 数据存储在指定的外部路径中
- 删除表时,仅删除表的元数据,数据不会被删除
- 适合与其他系统共享数据
使用场景:适用于数据需要与其他系统共享,或者数据由其他工具生成的场景。
1 | CREATE EXTERNAL TABLE external_table ( |
分区表
定义:分区表是一种特殊的表,数据按照某些分区键(Partition Key)进行划分。分区键可以是日期、地区等字段。
特点:
- 数据按分区键存储在不同的目录中,便于查询优化
- 查询时可以通过分区键过滤数据,提高查询效率
- 适合处理大规模数据集,尤其是数据按时间或类别划分的场景
使用场景:适用于数据量大且需要按时间或类别快速查询的场景。
1 | CREATE TABLE partitioned_table ( |
桶表
定义:桶表是一种将数据进一步细分的表类型。数据根据某个字段的哈希值被分配到不同的桶(Bucket)中。
特点:
- 数据在每个分区中被进一步细分为多个桶
- 适合进行高效的采样和分布式处理
- 查询时可以通过桶键进行优化,提高查询效率
使用场景:适用于需要对数据进行高效采样或分布式处理的场景。
1 | CREATE TABLE bucketed_table ( |