本文来自OPPO互联网技术团队,转载请注名作者。同时欢迎关注我们的公众号:OPPO_tech,与你分享OPPO前沿互联网技术及活动。
自03年开始,大数据三驾马车纷至沓来,同志们第一次拥有了分布式计算存储能力。
这种暴发户式的转变, 让人们莫名有了十足的底气:
“数据量大什么的怕你呀,数据格式什么的, 赶紧放进来就是了;别管了,就就就那个csv吧,快糙猛搞起来呀,大不了读的时候再解析校验啥的,读时校验(schema on read)有木有”
然而计算机的世界毕竟是机器的世界,你好懂了,机器就不好懂了。存储查询应用的效率的问题终于还是浮出了水面,大数据存储格式的进化之旅由此展开。
1. SequeceFile
文本存储很直接的问题就是存储效率很差,而解决这个问题第一直觉就是:那用zip,snappy压一压行不行?
存储可能行了,查询就不行了,因为大部分压缩格式一上,数据就变得不可分割了,那对应的mapper就只有一个,这并发起不来,分布式再牛逼也白搭呀。
那肿么解决呢,方法总比问题多,要不:那我把数据每隔多少条压成一个文件,多个文件这不就天生可以多并发了吗?
可是万万没想到有个问题叫做hdfs小文件过多的问题。
这这这逼出绝招啊:那把多个小文件合并怎么样!
比如下图所示:每10w行数据进行压缩,然后合并,并在文件头记录这些压缩块的偏移量。
SequenceFile的核心思想思想差不多如此,数据分块进行组织,块内可以采用压缩的方式。但它在每个块间设置一个同步标识用于分割块,而没有记录偏移量信息。
2. RCFile
Hive诞生之初,就以数仓工具的身份屹立大数据动物圈。而数仓面向的OLAP场景和关系数据库面向的OLTP场景最大的区别就在于:
- OLAP的查询往往是针对海量数据的部分列复杂的统计分析,在IO上的瓶颈体现在吞吐量上;
- 而OLTP则是以对少量数据的短平快的事务操作为特点,IO的延时是其核心问题。
所以关系数据库通常用B+tree精确索引或者Cache的方式加快查询。
因此按列进行连续存储的方式比按行将数据值串在一起连续存储的方式更合适于OLAP场景。
核心原因在于:
- 查询上:避免了无关列的加载;
- 存储上:同一列的数据更易于压缩。
而RCFile正是把列存的思想引入大数据的先驱者,如下图所示。
它的基本思想是将数据水平切分成一个个行组(row group,通常为一个hdfs block大小), 在每个行组内除了元数据和行组切分标识外,就是按照列值进行一波编码再对所有列进行压缩。
3. ORC&parquet
一般而言先驱者下场都不会太好,RCFile没有摆脱这个魔咒。
其实回看历史,原因也很显然:比起传统数仓中的列存而言,RCFile粗糙的不行不行的,要学就学全套呀!hive的开发者们总结其核心问题在于:
- 对数据类型不感知,限制了列存的存储高效性;
- 数仓里没有索引,令人发指。
于是乎得出结论:得改!
ORCFile也是在这个背景下,接过RCFile的大旗,应运而生,如下图所示。
从整体结构而言,也是将数据先进行水平切分成一个个stripe(其实和行组的概念是一样的),但在文件末尾(filefooter)加入了对每个行切分的偏移信息以及一些统计信息(某列的最大值最小值等等)。
偏移量的存在使得数据切分时,不用像rcfile那样遍历分散在整个文件中的同步标识确定每个stripe。而只需要读入文件尾部的几KB的数据,当然这也使ORC失去了追加写的能力。
另一方面统计信息的存在也使得数据的直接过滤掉某些stripe,比如假设有个查询:select a from table where b < 1
那么就可以只读取每个stripe的最大最小值,从而过滤掉那些b的最小值都大于等于1的stripe,从而减小记录的加载条数。
而在stripe内部,记录了列的类型,并根据列的类型进行编码。比如针对string的字典编码,可变长度的整型编码等等,都进一步加强了数据的存储效率。
parquet的结构和ORCFile很类似,主要的不同集中在对复杂结构的表示上,这里就不过多介绍了。
4. 最后
自此以后,列存的风吹遍了整个大数据生态圈。
carbondata采用多维排序的方式优化数据的列式布局,druid在列存之上,对维度列采用directory编码加bitmap索引的方式加速了对维度列的筛选和聚合.....
然而存储查询效率远不是大数据全部,实际中的应用问题同样重要。
19年4月,databrick公司平地一声雷,重磅开源的delta lake,给数据添加了acid特性,支持数据的并发读写存储的故事又要拉开一张大幕,世界就是这样精彩。
参考文献:
- RCFile: A fast and space-efficient data placement structure in MapReduce-based warehouse systems[C].
- Major technical advancements in apache hive[C].
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。