parquet和orc,parquet和orc的区别
[ms]为什么选择parquet及orc和parquet区别
spark支持parquet
hive支持parquet
csv存储的大小与实际文件大小一样,若没有压缩,占用容量=实际大小*副本数目
parquet完美实现分区过滤
列修剪
参考: 为什么选择parquet
orc:先划分行组,然后再划分成一列列再存储
HIVE存储格式ORC、PARQUET对比

求对比一下Apache开源列式存储引擎Parquet和ORC
并不是所有的数据都一直存储在内存中的。这是和Memcached相比一个最大的区别。当物理内存用完时,Redis可以将一些很久没用到的value交换到磁盘。
大数据常用文件格式介绍
图片看不见的话可以看我CSDN上的文章:
最近在做hdfs小文件合并的项目,涉及了一些文件格式的读写,比如avro、orc、parquet等。期间阅读了一些资料,因此打算写篇文章做个记录。
这篇文章不会介绍如何对这些格式的文件进行读写,只会介绍一下它们各自的特点以及底层存储的编码格式 。
[图片上传失败...(image-a5104a-1547368703623)]
使用sequencefile还可以将多个小文件合并到一个大文件中,通过key-value的形式组织起来,此时该sequencefile可以看做是一个小文件容器。
[图片上传失败...(image-4d03a2-1547368703623)]
Parquet是一个基于列式存储的文件格式,它将数据按列划分进行存储。Parquet官网上的文件格式介绍图:
[图片上传失败...(image-92770e-1547368703623)]
我们可以看出,parquet由几个部分构成:
[图片上传失败...(image-391e57-1547368703623)]
Orc也是一个列式存储格式,产生自Apache Hive,用于降低Hadoop数据存储空间和加速Hive查询速度。
[图片上传失败...(image-ba6160-1547368703623)]
目前列式存储是大数据领域基本的优化项,无论是存储还是查询,列式存储能做的优化都很多,看完上面对orc和parquet的文件结构介绍后,我们列式存储的优化点做一个总结:
在压缩方面 :
在查询方面 :
就网上找到的一些数据来看,Orc的压缩比会比Parquet的高一些,至于查询性能,两个应该不会差距太大。本人之前做过一个测试,在多数场景,hive on mr下,orc的查询性能会更好一些。换成hive on spark后,parquet的性能更好一些
本文介绍的4种大数据存储格式,2个是行式存储,2个是列式存储,但我们可以看到一个共同点:它们都是支持分割的。这是大数据文件结构体系中一个非常重要的特点, 因为可分割使一个文件可以被多个节点并发处理,提高数据的处理速度 。
另外,当前大数据的主要趋势应该是使用列式存储,目前我们公司已经逐步推进列式存储的使用,本人也在hive上做过一些测试,在多个查询场景下,无论是orc还是parquet的查询速度都完爆text格式的, 差不多有4-8倍的性能提升 。另外,orc和parquet的压缩比都能达到10比1的程度。因此,无论从节约资源和查询性能考虑,在大多数情况下,选择orc或者parquet作为文件存储格式是更好的选择。另外,spark sql的默认读写格式也是parquet。
当然,并不是说列式存储已经一统天下了,大多时候我们还是要根据自己的使用场景来决定使用哪种存储格式。
Sequencefile
Avro和Sequencefile区别
parquet
Orc
Orc和parquet的一些对比
「Hive进阶篇」详解存储格式及压缩方式
hive优化除了有hql语句逻辑优化,hql参数调优等等,还有一个不起眼的细节容易被忽视掉, 那便是hive数仓模型表的存储格式和压缩方式 ,hive底层数据是依托在hadoop,以HDFS文件存储在集群上的, hive数仓模型表选择一个合适的存储格式和压缩方式也是hive优化的一点 。
本篇就来聊一聊这块知识点吧。??
hive主要有textfile、sequencefile、orc、parquet 这四种存储格式,其中sequencefile很少使用,常见的主要就是orc和parquet这两种,往往也搭配着压缩方式合理使用。
建表声明语句是: stored as textfile/orc/parquet
行式存储,这是hive表的默认存储格式,默认不做数据压缩,磁盘开销大,数据解析开销大,数据不支持分片(即代表着会带来无法对数据进行并行操作)
行列式存储,将数据按行分块,每个块按列存储,其中每个块都存储着一个索引,支持none和zlib和snappy这3种压缩方式,默认采用zlib压缩方式,不支持切片,orc存储格式能提高hive表的读取写入和处理的性能。
列式存储,是一个面向列的二进制文件格式(不可直接读取),文件中包含数据和元数据,所以该存储格式是自解析的,在大型查询时效率很快高效,parquet主要用在存储多层嵌套式数据上提供良好的性能支持,默认采用uncompressed不压缩方式。
行存储引擎 :同一条数据的不同字段都在相邻位置,所以当要查找某一条记录所有数据时行存储查询速度比较快
列存储引擎 :以列来聚集数据,相同字段的值聚集在一起,所以当查询某一个指定列的所有数据时,列存储查询速度比较快
hive主要支持gzip、zlib、snappy、lzo 这四种压缩方式。
压缩不会改变元数据的分割性,即压缩后原来的值不变。
建表声明语句是: tblproperties("orc.compress"="SNAPPY")
压缩方式的评判标准主要有以下几点:
针对压缩方式做一个小结对比:
parquet和orc
Parquet文件是自解析的,文件中包括该文件的数据和元数据。在HDFS文件系统和Parquet文件中存在如下几个概念:
1)HDFS块(Block):它是HDFS上的最小的副本单位,HDFS会把一个Block存储在本地的一个文件并且维护分散在不同的机器上的多个副本,通常情况下一个Block的大小为256M、512M等。
2)HDFS文件(File):一个HDFS的文件,包括数据和元数据,数据分散存储在多个Block中。
3)行组(Row Group):按照行将数据物理上划分为多个单元,每一个行组包含一定的行数,在一个HDFS文件中至少存储一个行组,Parquet读写的时候会将整个行组缓存在内存中,所以如果每一个行组的大小是由内存大的小决定的。
4)列块(Column Chunk):在一个行组中每一列保存在一个列块中,行组中的所有列连续的存储在这个行组文件中。不同的列块可能使用不同的算法进行压缩。
5)页(Page):每一个列块划分为多个页,一个页是最小的编码的单位,在同一个列块的不同页可能使用不同的编码方式。
Parquet文件的格式如下图所示:
可以看出,存储格式中元数据索引信息是被存储在最后的,所以当读取某一行的数据的时候,就需要去定位最后的索引信息,最后才能去读取对应的行数据。元数据包括 Parquet 原始类型定义、Page类型、编码类型、压缩类型等等。
Parquet 支持嵌套结构的数据模型,而非扁平式的数据模型,这是 Parquet 相对其他列存比如 ORC 的一大特点或优势。支持嵌套式结构,意味着 Parquet 能够很好的将诸如 Protobuf,thrift,json 等对象模型进行列式存储。
Parquet 的数据模型也是 schema 表达方式,用关键字 message 表示。每个字段包含三个属性,repetition属性(required/repeated/optional)、数据类型(primitive基本类型/group复杂类型)及字段名。如:
和Parquet类似,ORC文件也是以二进制方式存储的,所以是不可以直接读取,ORC文件也是自解析的,它包含许多的元数据,这些元数据都是同构ProtoBuffer进行序列化的。ORC的文件结构如下图,其中涉及到如下的概念:
ORC文件:保存在文件系统上的普通二进制文件,一个ORC文件中可以包含多个stripe,每一个stripe包含多条记录,这些记录按照列进行独立存储,对应到Parquet中的row
group的概念。
文件级元数据:包括文件的描述信息PostScript、文件meta信息(包括整个文件的统计信息)、所有stripe的信息和文件schema信息。
stripe:一组行形成一个stripe,每次读取文件是以行组为单位的,一般为HDFS的块大小,保存了每一列的索引和数据。
stripe元数据:保存stripe的位置、每一个列的在该stripe的统计信息以及所有的stream类型和位置。
row group:索引的最小单位,一个stripe中包含多个row group,默认为10000个值组成。
stream:一个stream表示文件中一段有效的数据,包括索引和数据两类。索引stream保存每一个row group的位置和统计信息,数据stream包括多种类型的数据,具体需要哪几种是由该列类型和编码方式决定。
在ORC文件中保存了三个层级的统计信息,分别为文件级别、stripe级别和row group级别的,他们都可以用来根据Search ARGuments(谓词下推条件)判断是否可以跳过某些数据,在统计信息中都包含成员数和是否有null值,并且对于不同类型的数据设置一些特定的统计信息。
读取ORC文件是从尾部开始的,第一次读取16KB的大小,尽可能的将Postscript和Footer数据都读入内存。文件的最后一个字节保存着PostScript的长度,它的长度不会超过256字节,PostScript中保存着整个文件的元数据信息,它包括文件的压缩格式、文件内部每一个压缩块的最大长度(每次分配内存的大小)、Footer长度,以及一些版本信息。在Postscript和Footer之间存储着整个文件的统计信息(上图中未画出),这部分的统计信息包括每一个stripe中每一列的信息,主要统计成员数、最大值、最小值、是否有空值等。
接下来读取文件的Footer信息,它包含了每一个stripe的长度和偏移量,该文件的schema信息(将schema树按照schema中的编号保存在数组中)、整个文件的统计信息以及每一个row group的行数。
处理stripe时首先从Footer中获取每一个stripe的其实位置和长度、每一个stripe的Footer数据(元数据,记录了index和data的的长度),整个striper被分为index和data两部分,stripe内部是按照row group进行分块的(每一个row group中多少条记录在文件的Footer中存储),row group内部按列存储。每一个row group由多个stream保存数据和索引信息。每一个stream的数据会根据该列的类型使用特定的压缩算法保存。在ORC中存在如下几种stream类型:
PRESENT:每一个成员值在这个stream中保持一位(bit)用于标示该值是否为NULL,通过它可以只记录部位NULL的值
DATA:该列的中属于当前stripe的成员值。
LENGTH:每一个成员的长度,这个是针对string类型的列才有的。
DICTIONARY_DATA:对string类型数据编码之后字典的内容。
SECONDARY:存储Decimal、timestamp类型的小数或者纳秒数等。
ROW_INDEX:保存stripe中每一个row group的统计信息和每一个row group起始位置信息。
在初始化阶段获取全部的元数据之后,可以通过includes数组指定需要读取的列编号,它是一个boolean数组,如果不指定则读取全部的列,还可以通过传递SearchArgument参数指定过滤条件,根据元数据首先读取每一个stripe中的index信息,然后根据index中统计信息以及SearchArgument参数确定需要读取的row group编号,再根据includes数据决定需要从这些row group中读取的列,通过这两层的过滤需要读取的数据只是整个stripe多个小段的区间,然后ORC会尽可能合并多个离散的区间尽可能的减少I/O次数。然后再根据index中保存的下一个row group的位置信息调至该stripe中第一个需要读取的row group中。
ORC文件格式只支持读取指定字段,还不支持只读取特殊字段类型中的指定部分。
使用ORC文件格式时,用户可以使用HDFS的每一个block存储ORC文件的一个stripe。对于一个ORC文件来说,stripe的大小一般需要设置得比HDFS的block小,如果不这样的话,一个stripe就会分别在HDFS的多个block上,当读取这种数据时就会发生远程读数据的行为。如果设置stripe的只保存在一个block上的话,如果当前block上的剩余空间不足以存储下一个strpie,ORC的writer接下来会将数据打散保存在block剩余的空间上,直到这个block存满为止。这样,下一个stripe又会从下一个block开始存储。
由于ORC中使用了更加精确的索引信息,使得在读取数据时可以指定从任意一行开始读取,更细粒度的统计信息使得读取ORC文件跳过整个row group,ORC默认会对任何一块数据和索引信息使用ZLIB压缩,因此ORC文件占用的存储空间也更小,这点在后面的测试对比中也有所印证。