Hive基本概念
Hive由 Facebook 开源用于解决海量结构化日志的数据统计工具。Hive 是基于 Hadoop 的一个数据仓库工具,可以将结构化的数据文件映射为一张表,并提供类 SQL 查询功能。
Hive本质
- Hive本质将 HQL 转化成 MapReduce 程序
- Hive 处理的数据存储在 HDFS
- Hive 分析数据底层的实现是 MapReduce
- 执行程序运行在 Yarn 上
Hive的优缺点
优点:
- 操作接口采用类 SQL 语法,提供快速开发的能力;
- 避免了去写 MapReduce,减少开发人员的学习成本;
- Hive 的执行延迟比较高,因此 Hive 常用于数据分析,对实时性要求不高的场合;
- Hive 优势在于处理大数据,对于处理小数据没有优势,因为 Hive 的执行延迟比较 高;
- Hive 支持用户自定义函数,用户可以根据自己的需求来实现自己的函数。
缺点:
- 迭代式算法无法表达;
- 数据挖掘方面不擅长,由于 MapReduce 数据处理流程的限制,效率更高的算法却 无法实现;
- Hive 自动生成的 MapReduce 作业,通常情况下不够智能化;
- Hive 调优比较困难,粒度较粗。
Hive架构
用户接口Client
CLI(command-line interface)、JDBC/ODBC(jdbc 访问 hive)、WEBUI(浏览器访问 hive)
元数据Metastore
元数据包括:表名、表所属的数据库(默认是 default)、表的拥有者、列/分区字段、 表的类型(是否是外部表)、表的数据所在目录等
Hadoop
使用 HDFS 进行存储,使用 MapReduce 进行计算
驱动器Driver
- 解析器(SQL Parser):将 SQL 字符串转换成抽象语法树 AST;
- 编译器(Physical Plan):将 AST 编译生成逻辑执行计划;
- 优化器(Query Optimizer):对逻辑执行计划进行优化;
- 执行器(Execution):把逻辑执行计划转换成可以运行的物理计划。
Hive 和数据库比较
- Hive 是针对数据仓库应用设计的,而数据仓库的内容是读多写少的。因此,Hive 中 不建议对数据的改写,所有的数据都是在加载的时候确定好的。
- Hive 在查询数据的时候,由于没有索引,需要扫描整个表,因此延迟较高。另外一个导 致 Hive 执行延迟高的因素是 MapReduce 框架。由于 MapReduce 本身具有较高的延迟,因此在利用 MapReduce 执行 Hive 查询时,也会有较高的延迟。相对的,数据库的执行延迟较低。当然,这个低是有条件的,即数据规模较小,当数据规模大到超过数据库的处理能力的时候,Hive 的并行计算显然能体现出优势。
- 由于 Hive 建立在集群上并可以利用 MapReduce 进行并行计算,因此可以支持很大规模的数据;对应的,数据库可以支持的数据规模较小。
分区表
分区表实际上就是对应一个 HDFS 文件系统上的独立的文件夹,该文件夹下是该分区所 有的数据文件。Hive 中的分区就是分目录,把一个大的数据集根据业务需要分割成小的数据 集。在查询时通过 WHERE 子句中的表达式选择查询所需要的指定的分区,这样的查询效率 会提高很多。
文件存储格式
Hive 支持的存储数据的格式主要有:TEXTFILE 、SEQUENCEFILE、ORC、PARQUET。
TEXTFILE 和 SEQUENCEFILE 的存储格式都是基于行存储的;ORC 和 PARQUET 是基于列式存储的。
TextFile
默认格式,数据不做压缩,磁盘开销大,数据解析开销大。可结合 Gzip、Bzip2 使用,但使用 Gzip 这种方式,hive 不会对数据进行切分,从而无法对数据进行并行操作。
Orc
每个 Orc 文件由 1 个或多个 stripe 组成,每个 stripe 一般为 HDFS的块大小,每一个 stripe 包含多条记录,这些记录按照列进行独立存储,对应到 Parquet中的 row group 的概念。每个 Stripe 里有三部分组成,分别是 Index Data,Row Data,Stripe Footer。
- Index Data:一个轻量级的 index,默认是每隔 1W 行做一个索引。这里做的索引应该 只是记录某行的各字段在 Row Data 中的 offset。
- Row Data:存的是具体的数据,先取部分行,然后对这些行按列进行存储。对每个 列进行了编码,分成多个 Stream 来存储。
- Stripe Footer:存的是各个 Stream 的类型,长度等信息。
每个文件有一个 File Footer,这里面存的是每个 Stripe 的行数,每个 Column 的数据类 型信息等;每个文件的尾部是一个 PostScript,这里面记录了整个文件的压缩类型以及 FileFooter 的长度信息等。在读取文件时,会 seek 到文件尾部读 PostScript,从里面解析到File Footer 长度,再读 FileFooter,从里面解析到各个 Stripe 信息,再读各个 Stripe,即从后往前读。
Parquet
Parquet 文件是以二进制方式存储的,所以是不可以直接读取的,文件中包括该文件的 数据和元数据,因此 Parquet 格式文件是自解析的。
- 行组(Row Group):每一个行组包含一定的行数,在一个 HDFS 文件中至少存储一 个行组,类似于 orc 的 stripe 的概念。
- 列块(Column Chunk):在一个行组中每一列保存在一个列块中,行组中的所有列连 续的存储在这个行组文件中。一个列块中的值都是相同类型的,不同的列块可能使用不同的算法进行压缩。
- 页(Page):每一个列块划分为多个页,一个页是最小的编码的单位,在同一个列块 的不同页可能使用不同的编码方式。
在存储 Parquet 数据的时候会按照 Block 大小设置行组的大小,由于一般情况下每一个 Mapper 任务处理数据的最小单位是一个 Block,这样可以把每一个行组由一个 Mapper 任务处理,增大任务执行并行度。
Hive数据类型
| Hive数据类型 | Java数据类型 |
|---|---|
| TINYINT | byte |
| SMALINT | short |
| INT | int |
| BIGINT | long |
| BOOLEAN | boolean |
| FLOAT | float |
| DOUBLE | double |
| STRING | string |
| TIMESTAMP | |
| BINARY | |
| STRUCT | |
| MAP | |
| ARRAY |