5000字6图 | 一篇文章帮你理解大数据列式存储(干货收藏)

什么是列式存储
  • 所谓行式存储,指存储结构化数据时,在底层的存储介质上,数据是以行的方式来组织的,即存储完一条记录的所有字段,再存储下一条数据的所以字段,以此类推;

  • 所谓列式存储,指存储结构化数据时,在底层的存储介质上,数据是以列的方式来组织的,即存储完若干条记录的首个字段后,再存储这些记录的第二个字段,然后是这些记录的第三个字段,以此类推,当这些记录的所有字段存储完毕后,再按照这种方式,组织存储下一批若干条记录的所有字段;

比如需要存储以下记录:

              姓名年龄工资
              小张1810000
              小王1911000
              小李2012000
              小赵2113000
              小周2214000
              小吴2315000
              小郑2416000
              小杨2517000

这行存储格式,底层是这样组织的:(示意图)e3c7e41b0b485bb77e8f89b5dde00f39.png

而列存储格式,底层是这样组织的:(示意图)3845b5f10c6c0b874360e1e855682d59.png

说明:

  • 以上只是示意图,实际存储时,往往还会存储一些元数据,比如校验信息,统计信息等等;(列式存储往往会存储更多的元数据信息,以便于检索/查询/统计等)

  • 行存储与列存储,存储的都是结构化数据;(非结构化数据,就无所谓行和列了)

  • 行存储和列存储,描述的是底层存储介质上,数据的组织形式,而存储介质可以是磁盘,也可以是内存;存储介质的上次建筑,可以是文件系统,也可以是对象存储;

  • 很多数据库,在底层即支持行存储,也支持列存储,这两者有时是同时混合使用的;(比如 oracle12c,就引入了对 In-Memory Column Store 的支持;再比如 TiDB, 底层同时支持行存储引擎 TiKV 和 列存储引擎 TiFlash);

深入了解列式存储 - 以 Parquet 为例

说到当下最流行的开源列式存储引擎,就非 apache parquet 莫属了。

  • 绝大多数计算引擎,比如 apache spark/presto/impala/flink, 都将 parquet 作为首选的列示存储引擎;

  • orc 是 apache hive 社区推出的,另一款开源列示存储引擎;

  • apache hive 在早期只支持 orc 列示存储的基础上,又扩展了对 parquet 的支持;

有鉴于此,我们有必要以 parquet 为例,来深入了解下列式存储。

以下是 parquet 底层,数据的组织格式:

b425c0dcadfaa51fff27bcf1069180b7.png
image

相关术语解释如下:

  • Block (hdfs block): 指 hdfs 文件系统的 block,parquet 是在 hdfs 文件之上的数据组织格式;(当然现在很多对象存储系统,比如 S3,也支持 parquet 存储格式);

  • File: 指 hdfs 文件,使用 parquet 格式时,每个 hdfs 文件底层必须包括 parquet 元数据 - 事实上该文件底层可以不包含数据,但必须包含元数据;(当然现在很多对象存储系统,比如 S3,也支持 parquet 存储格式);

  • Row group: 文件底层的所有数据,在逻辑上被水平切割,每个 row group 存储的都是一份这些被水平切割后的数据。(row group 是对数据的水平切分比如上图中,就显示了 row group 0 和 row group1 两个 row group);

  • Column chunk: 每个 row group 底层都包含一系列 column chunk,每个colum 都有一个对应的 column chunk;(数据有多少列,水平切割的每个 row group底层,就有多少个 column chunk);

  • Page: Column chunks 被进一步切分为若干个 page 页,page 是压缩和编码的最小单位;(比如上如,row group0 的 Column a,就显示了两个 page: page a 和 page b);

概括如下:

  • 每个文件由一个或多个 row group 构成,每个 row group 包含了多个 column chunk (column chunk 和 column 是 一一对应的),Column chunks 包含了一个或多个 page;

  • MR 等计算作业,其并行操作的单位是 File/Row Group;

  • IO 的单位是 Column chunk;

  • 编码和压缩的单位是 Page;

行式存储与列式存储的优劣势都有哪些

通过上述对底层数据组织格式的对比,不难发现,行存储有以下特点:

  • 行存储将每条数据的所有列连续存储在一起,一条记录接着一条记录;

  • 行存储中数据写入的成本较低,适合数据有频繁更新的场景;

  • 通过使用索引,能大幅提高行存储的数据查询速度;

  • 行存储是传统的数据组织形式,更适合传统的 OLTP 系统;(OLTP 数据库表的设计强调范式,底层一般有多张有关联关系的窄表)

而列存储有以下特点:

  • 列存储将多行记录的列连续存储在一起,一列接着一列;

  • 由于连续存储在一起的列的数据类型都一样,所以数据压缩率更高,更省存储空间;

  • 列存储中数据查询的成本较低,特别适合分析时只查询部分列的场景,因为不需要扫描/读取不需要查询的列;

  • 列存储由于数据更新成本较高,一般适合读多写少的场景;(但是不代表不能更新!)

  • 列存储是新型数据组织形式,更适合 OLAP 分析型系统;(OLAP数据库表的设计强调反范式,底层一般是星型模式的若干张事实表和维度表,倾向使用大宽表)

列式存储与数据质量

各厂各司在其数据仓库或数据湖泊的数据规范部分,大都强调要尽可能地使用列式存储格式,而尽可能不要使用行式存储格式。

究其原因,一方面是列式存储相比行式存储,其压缩率更高读写效率更快;另一方面是因为,相比行式存储,列式存储的数据质量更高!

之所以说列式存储能提高数据质量,更准确地说,是有些行式存储会降低数据质量,比如 csv/tsv 等 TextFile。

比如,以我们熟悉的 HIVE 为例,一个常见的 DDL 语句如下:

CREATE TABLE student_text_test(                       
   id double,                                     
   name string,                                   
   sex double,                                    
   age double,                                    
   class double,                                  
   address string)    
   ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n'
 STORED AS TEXTFILE;
  • 大家可以看到,TextFile 的 DDL 语句中,需要通过 xx terminated by xx 来指定列分隔符和行分隔符(列分隔符默认是'\001',行分隔符默认是'\n');

  • 而上游rdbms表中某些字段,可能会包含特殊字符比如换行符,此时就可能会跟上述textfile 表的 DDL 语句中指定的列分隔符或分隔符冲突;

  • 后续通过数据同步工具比如 sqoop/datax/spark sql 等同步上游数据到 hive中 textfile 格式的表时,同步作业可以执行成功;

  • 但是后续再查询该同步的 textfile 格式的表时,因为大数据schema on read 的特性,在读数据时按就会按照 DDL 中指定的行和列分隔符来切割数据,此时就可能会因为行分隔符造成数据切割混乱,从而查出大量 NULL 字段的错乱数据;

  • 不幸的是,上游 RDBMS 中的数据往往不受大数据部门管控,会出现各种各样的奇怪数据;

  • 更不幸的是,目前hive的textfile只支持\n作为行分隔符(验证了cdh6.3,也就是hive2.1)

所以,正是出于数据质量的原因,各厂各司在其数据仓库或数据湖泊的数据规范部分,大都强调:

  • 要尽可能地使用列式存储格式比如orc/parquet,而尽可能不要使用行式存储格式textfile;

  • 数仓中各层,包括 ods/dwd/dws/ads ,以及业务临时表与技术临时表,都尽量不要使用textfile;

  • 除非是选用的数据同步工具不支持orc/parquet(比如sqoop),且此时也仅仅只能在 ods层的落地表中使用textfile, 后面 dws等各层需要切换使用列示存储 orc/parquet;

  • 必要时,对数据同步工具重新进行技术选型,比如抛弃不支持列式存储的 sqoop, 而选用支持列式存储的 spark sql/datax 等。

--END--

54690aab828ae036b8e1597738132bc4.png

非常欢迎大家加我个人微信

拉你进大数据架构技术群,有问题我们在群内一起讨论

a874522d7d91b597bc6483052901891d.png

长按上方扫码二维码,加我微信,拉你进群

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值