目录
一、前言
二、存储格式
2.1、文本格式(TextFile)
2.1.1、定义与特点
2.1.2、存储与压缩
2. 1.3、使用场景
2.2、行列式文件(ORCFile)
2.2.1、ORC的结构
2.2.2、ORC的数据类型
2.2.3、ORC的压缩格式
2.2.3、ORC存储格式建表
2.3、Apache Parquet
2.3.1、Parquet基本结构
2.3.2、Parquet的压缩格式
1、Snappy:
2、Zlib:
3、LZO:
4、Gzip:
三、ORC与Parquet的使用
一、前言
本文重点讲解Hive的存储格式,它是Hive操作数据的基础。选择一种合适的底层数据存储文件格式,即使不改变sql的情况下,对性能也是有很大的提升。同时,找工作面试也会问存储格式相关的题目。分享给大家,一起学习探讨。
二、存储格式
Hive数据存储支持的格式有文本格式(TextFile)、二进制序列化文件 (SequenceFile)、行列式文件(RCFile)、Apache Parquet和优化的行列式文件(ORCFile)。其中,ORCFile和Apache Parquet,以其高效的数据存储 和数据处理性能得以在实际的生产环境中大量运用。
本文将讲解文本格式(TextFile)、优化的行列式文件(ORCFile)、Apache Parquet。
2.1、文本格式(TextFile)
2.1.1、定义与特点
TextFile即正常的文本格式,是Hive中最基础且默认的存储格式。这种格式的文件在HDFS(Hadoop Distributed File System)上以明文形式存储,因此可以直接通过hadoop fs -cat命令查看,或者从HDFS下载后直接读取。TextFile的存储特点是每一行通常代表一条记录,字段之间可以通过指定的分隔符进行分割。
当你创建一个Hive表时,如果没有指定存储格式,那么默认就会使用TextFile。例如:
CREATE TABLE my_table(id INT, name STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n';
在这个例子中,没有指定存储格式,所以默认使用TextFile。
如果你想指定使用TextFile,可以这样写:
CREATE TABLE my_table(id INT, name STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
STORED AS TEXTFILE;
2.1.2、存储与压缩
-
存储方式:TextFile以行式存储为主,即数据按行组织,每行包含完整的记录。这种存储方式适合字段较少或经常需要获取全字段数据的场景。
-
压缩支持:TextFile默认不进行压缩,但支持结合Gzip、Bzip2、Snappy等压缩算法使用。然而,当TextFile表压缩后再进行解压(即反序列化)时,会耗费较多的时间。此外,压缩后的TextFile文件不支持split,这意味着Hive无法对数据进行并行操作,从而可能影响查询性能。
2. 1.3、使用场景
仅仅用在文本文件导入到Hive的表中,需要建立这种表或者适合字段较少或经常需要获取全字段数据。
2.2、行列式文件(ORCFile)
ORC存储的文件是一种带有模式描述的行列式存储文件。ORC有别于传统的数据存储文件,它会将数据先按行组进行切分,一个行组内部包含若干行,每一行组再按列进行存储,如图下图所示:
2.2.1、ORC的结构
我们知道传统的行式数据库,数据按行存储,在没有使用索引的情况下,如果要查询一个字段,需要将整行的数据查找出来,再找到相应的字段,这样的操作是比较消耗I/O资源的。最初的解决方式是建立Hive索引。
Hive建立索引是一项比较消耗集群资源的工作,并且需要时刻关注是否更新。数据如有更新,就需要对索引进行重建。数据有更新却没有及时重建或者忘了重建,则会引发使用过程的异常。正是建立Hive索引成本高,又极容易引发异常,所以在实际生产中,Hive索引很少被用到。这时候有些人就想到使用列式存储。
相比于行式存储,列式存储的数据则是按列进行存储,每一列存储一个字段的数据,在进行数据查询时就好比走索引查询,效率较高。但是如果需要读取所有的列,例如一个数据平台刚接入数据,需要对所有的字段进行校验过滤,在这种场景下列式存储需要花费比行式存储更多的资源,因为行式存储读取一条数据只需要一次I/O操作,而列式存储则需要花费多次,列数越多消耗的I/O资源越多。
ORC的行列式存储结构结合了行式和列式存储的优点,在有大数据量扫描读取时,可以按行组进行数据读取。如果要读取某个列的数据,则可以在读取行组的基础上,读取指定的列,而不需要读取行组内所有行的数据及一行内所有字段的数据。
ORC文件结构由三部分组成:
1、条带(stripe):ORC文件存储数据的地方,结构同样可以分为三部分:
1)index data:保存了所在条带的一些统计信息,以及数据在stripe中的位置索引信息。
2)rows data:数据存储的地方,由多个行组构成,数据以流(stream)的形式进行存储。存储两部分的数据,即metadata stream和data stream。
a、metadata stream:用于描述每个行组的元数据信息。
b、data stream:存储数据的地方。
3)stripe footer:保存数据所在的文件目录。
2、文件脚注(file footer):包含了文件中stripe的列表,每个stripe的行数,以及每个列的数据类型。它还包含每个列的最小值、最大值、行计数、求和等聚合信息。
3、postscript:含有压缩参数和压缩大小相关的信息。
简要了解完ORC的结构可以得知,ORC在每个文件中提供了3个级别的索引。
1、文件级:这一级的索引信息记录文件中所有stripe的位置信息,以及文件中所存储的每列数据的统计信息。
2、条带级别:该级别索引记录每个stripe所存储数据的统计信息。
3、行组级别:在stripe中,每10 000行构成一个行组,该级别的索引信息就是记录这个行组中存储的数据的统计信息。
程序可以借助ORC提供的索引加快数据查找和读取效率。程序在查询ORC文件类型的表时,会先读取每一列的索引信息,将查找数据的条件和索引信息进行对比,找到满足查找条件的文件。接着根据文件中的索引信息,找到存储对应的查询条件数据stripe,再借助stripe的索引信息读文件中满足查询条件的所有stripe块。之后再根据stripe中每个行组的索引信息和查询条件比对的结果,找到满足要求的行组。
2.2.2、ORC的数据类型
Hive在使用ORC文件进行存储数据时,描述这些数据的字段信息、字段类型信息及编码等相关信息都是和ORC中存储的数据放在一起的。ORC中每个块中的数据都是自描述的,不依赖外部的数据,也不存储在Hive的元数据库中。ORC提供的数据数据类型包含如下内容:
1、整型:包含boolean(1bit)、tinyint(8bit)、smallint(16bit)、int(32bit)、bigint(64bit)。
2、浮点型:包含float、double、decimal。
3、字符串类型:包含string、char、varchar。
4、二进制类型:包含binary。
5、日期和时间类型:包含timestamp和date。
6、复杂类型:包含struct、list、map和union类型。
目前ORC基本已经兼容了日常所能用到的绝大部分的字段类型。另外,ORC中所有的类型都可以接受NULL值。
Hive在创建ORC类型的表时,表中的列是按照struct形式组织,struct是按照树的方式来组织并描述字段的。例如:
create table test(
a int
b map<string,struct<myString : string,myDouble: double>>,
c string
)
2.2.3、ORC的压缩格式
ORC存储格式支持的压缩格式有限:None(不压缩),Zlib和Snappy三种压缩格式。默认为Zlib压缩,不支持切分。
1、Zlib
无损压缩算法,提供了较高的压缩比。它通常用于需要较高压缩率的场景,但压缩和解压缩速度相对较慢。适用于对压缩率有较高要求且可以容忍一定延迟的场景。
2、Snappy
以较快的压缩和解压缩速度著称,但压缩比通常低于ZLIB。适用于需要频繁读写操作的数据处理任务,特别是在读取性能至关重要的分析型工作负载中。
2.2.3、ORC存储格式建表
CREATE TABLE IF NOT EXISTS orc_table (
id INT,
name STRING,
value DOUBLE
)
STORED AS ORC;
2.3、Apache Parquet
Parquet是另外的一种高性能行列式的存储结构,可以适用多种计算框架,被多种查询引擎所支持,包括Hive、Impala、Drill等。
2.3.1、Parquet基本结构
在一个Parquet类型的Hive表文件中,数据被分成多个行组,每个列块又被拆分成若干的页(Page),如图下图所示。
Parquet在存储数据时,也同ORC一样记录这些数据的元数据,这些元数据也同Parquet的文件结构一样,被分成多层文件级别的元数据、列块级别的元数据及页级别的元数据。
程序可以借助Parquet的这些元数据,在读取数据时过滤掉不需要读取的大部分文件数据,加快程序的运行速度。同ORC的元数据一样,Parquet 的这些元数据信息能够帮助提升程序的运行速度,但是ORC在读取数据时又做了一定的优化,增强了数据的读取效率。下面用两个例子来看看程序在读取Parquet和ORC文件时的差别。
2.3.2、Parquet的压缩格式
Parquet存储格式支持的压缩格式:Uncompress(不压缩)、Zlib、LZO、Snappy、Gzip。默认为不压缩。
1、Snappy
以较快的压缩和解压缩速度著称,但压缩比通常低于ZLIB。适用于需要频繁读写操作的数据处理任务,特别是在读取性能至关重要的分析型工作负载中。
2、Zlib
无损压缩算法,提供了较高的压缩比。它通常用于需要较高压缩率的场景,但压缩和解压缩速度相对较慢。适用于对压缩率有较高要求且可以容忍一定延迟的场景。
3、LZO
通常用于需要快速读取和写入数据的场景。LZO提供了适中的压缩比和速度,但可能需要额外的解压缩库支持。适用于需要处理大文件且希望避免数据倾斜的场景,因为LZO压缩的文件可以更容易地进行分割和并行处理。
4、Gzip
一种广泛使用的无损压缩算法,提供了较高的压缩比。然而,其压缩和解压缩速度相对较慢,可能会在处理大量数据时引入延迟。适用于存储空间有限且对压缩率有较高要求的场景,但需要注意其可能对查询性能产生的影响。
2.3.3、Parquet存储格式建表
CREATE TABLE my_parquet_table (
id INT,
name STRING,
value DOUBLE
)
STORED AS PARQUET;
三、ORC与Parquet的使用
在Hive的性能比较中,同样的数据进行sql查询,使用ORC读取的行远小于Parquet,ORC的效率比较高。
实际生产中,使用Parquet存储格式,LZO压缩的方式更为常见,这种情况可以避免由于读取不可切分大文件导致的数据倾斜。如果数据并不是特别大的情况系啊,使用ORC存储格式,Snappy压缩效率还是非常好的。
PS:有问题,欢迎大家指正讨论