列式存储与传统的行式存储异同及优势

行式存储可以看成是一个行的集合,其中每一行都要求对齐,哪怕某个字段为空(下图中的左半部分),而列式存储则可以看成一个列的集合(下图中的右半部分)。列式存储的优点很明显,主要有以下 4 点:

  • 查询时可以只读取涉及的列(选择操作),并且列可以直接作为索引,非常高效,而行式存储则必须读入整行。
  • 列式存储的投影操作非常高效。
  • 在数据稀疏的情况下,压缩率比行式存储高很多,甚至可以考虑将相关的表进行预先连接,来完全避免投影操作。
  • 因为可以直接作用于某一列上,聚合分析非常迅速。
  • 行式存储一般擅长的是插入与更新操作,而列式存储一般适用于数据为只读的场景。对于结构化数据,列式存储并不陌生。因此,列式存储技术经常用于传统数据仓库中。

下图分别展示了行式存储和列式存储的区别。
列式存储与传统的行式存储异同及优势

列式存储的实现

Apache Parquet

Apache Parquet 是 Dremel 的开源实现,它最先是由 Twitter 与 Cloudera 合作开发并开源,和 Impala 配合使用。Parquet 支持几乎 Hadoop 生态圈的所有项目,与数据处理框架、数据结构以及编程语言无关。

Apache ORC

Apache ORC(OptimizedRC file)来源于 RC(RecordColumnar file)格式,但目前已基本取代 RC 格式。ORC 提供 ACID 支持、也提供不同级别的索引,如布隆过滤器、列统计信息(数量、最值等),和 Parquet 一样,它也是自描述的数据格式,但与 Parquet 不同的是,ORC 支持多种复杂数据结构,如集合、映射等。ORC 与 Presto 配合使用,效果非常好。

Apache CarbonData

CarbonData 是华为开源的一种列式存储格式,是专门为海量数据分析和处理而生的。CarbonData 于 2016 年开源,目前发展非常迅猛,与 Apache Kylin 并列为由国人主导的两个Apache *项目。它的设计初衷源于,在很多时候,对于同样一份数据,处理方式是不同的,比如以下几种处理方式:

全表扫描,或者选取几列进行过滤;

随机访问,如行键值查询,要求低延迟;

ad-hoc 交互式分析,如多维聚合分析、上卷、下钻、切片等。

不同的处理方式对于数据格式的需求侧重点是不同的,但 CarbonData 旨在为大数据多样化的分析需求提供一种统一的数据格式。CarbonData 的设计目标为:

支持低延迟访问多种数据访问类型;
允许在压缩编码过的数据上进行快速查询;
确保存储空间的高效性;
很好地支持 Hadoop 生态系统;
读最优化的列式存储;
利用多级索引实现低延迟;
支持利用列组来获得基于行的优点;
能够对聚合的延迟解码进行字典编码。
如下图所示,这是一个 CarbonData 数据文件,也是 HDFS 上的一个数据块,每个文件由 File Header、File Footer 与若干个 Blocklet 组成,其中 File Header 保存了文件版本号、Schema 以及更新时间戳;File Footer 包含了一些统计信息(每个 Blocklet 的最值)、多维索引等。一个 Blocklet 的默认大小为 64MB,包含多个 Column Page Group,Blocklet 可以看成一个表的水平切片,这个表有多少列,就有多少个 Column Page Group,在一个 Column Page Group 中,一列被分为若干个连续文件,每一个文件被称为 Page,一个 Page 默认为 32000 行,如下图所示。

列式存储与传统的行式存储异同及优势

CarbonData 在设计理念上没有采取 Dremel 提出的嵌套的列式存储,而是引入了索引和元数据的设计,但仍然属于列式存储格式。ORC 的压缩率最高,而 CarbonData 在 Spark 批处理这种场景下,性能表现得非常好,是一种非常有前景的技术。

列式存储的压缩率如此之高,从本课时的第一张图也可以看出原因,列式存储作为列的集合,空间几乎没有多余的浪费。如此高的压缩效率也带来了一个优化思路:可以将若干相关的表预先进行连接,连接而成的表可以看成是一张稀疏的宽表,这张宽表对分析来说就非常友好了,但由于采用了列式存储,所以宽表所占的空间并不是指数上涨而是线性增加。在这种场景下,列式存储使得空间换时间成为可能。