数据平台的功能简而言之只有两个:存储数据和搜索数据。
在现实生活中存在着两个不同的数据处理模型,一个是OLTP,另一个是OLAP。两者的区别不在这篇文章详细叙述,感兴趣的可以阅读参考文章。因为OLAP和OLTP所面临的困境是不一样的,所以两个选择的数据存储方式也就不一样了。OLTP的数据存储模型大多逃不过Key-Value、B-Tree、LSM-Tree三种行式存储,而OLAP对应的则是列式存储。
随着时代的发展,也诞生了类似C-Store、TiFlash/Tikv的混合存储方式:基于分布式系统的多副本模式,选择一部分副本使用行式存储,另一部分副本使用列式存储,根据SQL特性选择最合适的数据处理方式。
广义上的数据平台的存储数据的方式应该兼容并蓄,根据业务的不同,选择相应的数据存储格式。本文将聚焦于数据平台中关于数据仓库的部分,简单的讨论列式存储及其相关的实现。其余部分留待后文分享,数据模型的简要分析可参考旧文。
列式存储诞生于数据仓库独有的分析模式:星型和雪花型模式。对于两种模型而言,它们需要数据平台提供:大规模读取和写入数据的能力;查询时不需要访问所有列,按需返回对应列的数据;并发不要求太高,容忍一定的时延。列式存储满足了这些要求。
想象一下,在数据仓库中往往都会存在成百上千列的宽表,当使用行式存储引擎时需要将数据平台中存储的数据里所有行从磁盘加载到内存中,解析它们,并过滤掉那些不符合要求的条件。但是当使用列式存储引擎时,只需要加载查询条件中对应的列,不需要所有行的数据,因此对于系统的负荷也相应地少了很多。
而列式存储的想法很简单:不要将数据按行存储在一起,而是按列存储在一起。所以对于列式存储而言,它依赖于每一个列文件都有着相同的顺序。
基于上述的想法,列式存储可以更好的根据每一列的特性对数据进行压缩(列压缩),使用位图去索引每一列的值(向量化),更多的优化技术详见参考文章。
列式存储的实现有很多种,最常见的就是Parquet、ORC。
Parquet和ORC都是Apache的顶级项目,需要根据计算引擎的不同选择不同的存储格式。
因为传统的HDFS是不支持对数据进行删改查的,所以就有一些有趣的项目扩展了HDFS的能力,比如Apache Hudi和Spark delta lake。两者的设计都是通过metadata去管理某个文件夹下的数据,从而实现对数据的增量处理。
基于Hadoop的数据仓库的存储格式选择是一个有趣的话题。选择一个适合集群计算引擎的存储格式,会大大提高数据查询效率,减少数据的存储空间。而对于数据仓库的设计模式而言,列式存储是最好的选择;不过随着技术的发展,类似HTAP的混合存储方式会成为主流。