从NSM到Parquet:存储结构的衍化

时间:2021-09-04 13:52:58

http://blog.csdn.net/dc_726/article/details/41777661

为了优化MapReduce及MR之前的各种工具的性能,在Hadoop内建的数据存储格式外,又涌现了一批各种各样的存储方式。如优化Hive性能的RCFile,以及配合Impala实现出Google Dremel功能(类似甚至是功能的超集)的Parquet等。今天就来一起学习一下HDFS中数据存储的进化历程。

数据摆放结构

数据摆放结构(data placement structure),顾名思义,就是数据如何在HDFS中放置和存储的。这种摆放结构对于像Hive这种,HDFS之上的查询工具来说是非常重要的,摆放的结构和策略会直接影响Hive查询引擎的实现和性能。从Hive的角度来看,数据摆放结构就是:年就已经提出来了。

从NSM到Parquet:存储结构的衍化

下图就是HDFS中列式存储的样子。

从NSM到Parquet:存储结构的衍化

现今有很多列式存储的NoSQL数据库,在Hadoop中最典型的例子就是HBase了。(待补充:HFile结构,以及HBase如何解决列式存储的性能开销等问题)

混合型的存储结构

PAX(The Partition Attributes Across Model)是一种典型的混合型实现,与前面两种传统存储方式的具体模型比较:

从NSM到Parquet:存储结构的衍化

引用一篇文章

NSM(N-ary Storage Model),即基于行的存储模型。随着硬件的发展,NSM对于缓存的利用率较低。NSM在每个磁盘页面中连续的存储记录,使相对页面的偏移记录每条记录的开始。

DSM(Decomposition Storage Model)。列存储模型并不是一个新鲜的概念,在1985年就已经提出,2005年左右随着数据分析应用的广泛开展获得新生。对数据的使用,特别是分析的需求,常常只使用一条记录的一部分数据。为了减少IO的消耗,提出了“分解存储模型”。DSM将关系垂直分为n个子关系,属性仅当需要时才加以存取访问。对于涉及多个属性的查询来说需要额外的开销用于连接子关系。

PAX(Partition Attribute Across)。PAX是记录在页面中的混合布局方式,结合了NSM和DSM的优点,避免了对主存不需要的访问。PAX首先将尽可能多的关系记录采用NSM方式加以存储。在每个页面内,使用按属性和minipage进行类似于DSM的存储。在顺序扫描时,PAX充分利用了缓存的资源。同时,所有的记录都位于相同的页面。对于记录的重构操作,仅仅在minipage之间进行,并不涉及跨页的操作。相对于DSM来说,对于多属性的查询来说PAX优于DSM,因为DSM需要更多的跨页重构时间。

混合存储模型,我们可以将所有的数据都理解为由Key/Value/Description(column name)构成的三元组存储模型。KV模型允许你按照你想要的模式来组织数据的存储,如果应用总是按照行来访问的(比如总是访问某个用户的大部分数据),那么就可以把数据按照同一个Key组织在一起(实际上就是NSM),而如果某个应用总是分析汇总查询,可以按照Description(column name)将数据组织在一起(DSM或者PAX的实现)。

Record Columnar File(RCFile)借鉴了PAX存储模型,混合了行式和列式存储。通过先进行水平分区,再垂直分区,并且保证同一行的数据一定在同一个结点

从NSM到Parquet:存储结构的衍化

RCFile基于HDFS,一个表可以包含多个块,每块内按行组(row group)进行组织。每个行组包含:用来分隔行组的sync标记,元数据头,以及按列式存储的表数据。其中元数据头和表数据是分别独立压缩的。元数据头使用RLE(runtime length encoding)算法,而表数据使用gzip算法,并配合延迟解压技术(lazy decompression)。RCFile只支持追加(append)写数据。

Parquet

Parquet是Cloudera和Twitter合作的项目,实现了Dremel论文中定义的数据模型,能够以列式存储的二维表来表示嵌套记录,同时也支持像Pig和Hive等行式查询引擎。Parquet的存储结构与RCFile有雷同之处,例如RowGroup包含多个column,而每个column则由page组成,page中的每一项是由repetition level、definition level和value组成的三元组。

从NSM到Parquet:存储结构的衍化

Parquet中使用多种编码压缩技术。首先,对于不重复值较少的列可以进行字典编码(dictionary encoding),例如不重复值<5w个,这要比gzip, lzo, snappy等重型算法要更好、更快。此外,对于字典编码后的列值,repetition和definition level这种小整数,还可以进行位压缩(bit packing),用能够装下这些小整数的最少的位来保存它们。最后,结合着前两种方法,还可以进一步进行RLE(run length encoding)压缩,这对definition level这种比较稀疏的列来说效果比较好。

从NSM到Parquet:存储结构的衍化

参考资料

1 RCFile: A Fast and Space-efficient Data Placement Structure

2 A Multi-resolution Block Storage Model for Database Design

3 Data Page Layouts for Relational Databases on Deep Memory Hierarchies

4 InnoDB Internals: InnoDB File Formats and Source Code Structure

5 Parquet: An Open Columnar Storage for Hadoop