本文来自OPPO互联网技术团队,转载请注名做者。同时欢迎关注咱们的公众号:OPPO_tech,与你分享OPPO前沿互联网技术及活动。数据库
自03年开始,大数据三驾马车纷至沓来,同志们第一次拥有了分布式计算存储能力。apache
这种暴发户式的转变, 让人们莫名有了十足的底气:并发
“数据量大什么的怕你呀,数据格式什么的, 赶忙放进来就是了;别管了,就就就那个csv吧,快糙猛搞起来呀,大不了读的时候再解析校验啥的,读时校验(schema on read)有木有”
然而计算机的世界毕竟是机器的世界,你好懂了,机器就很差懂了。存储查询应用的效率的问题终于仍是浮出了水面,大数据存储格式的进化之旅由此展开。app
文本存储很直接的问题就是存储效率不好,而解决这个问题第一直觉就是:那用zip,snappy压一压行不行?分布式
存储可能行了,查询就不行了,由于大部分压缩格式一上,数据就变得不可分割了,那对应的mapper就只有一个,这并发起不来,分布式再牛逼也白搭呀。工具
那肿么解决呢,方法总比问题多,要不:那我把数据每隔多少条压成一个文件,多个文件这不就天生能够多并发了吗?布局
但是万万没想到有个问题叫作hdfs小文件过多的问题。大数据
这这这逼出绝招啊:那把多个小文件合并怎么样!优化
好比下图所示:每10w行数据进行压缩,而后合并,并在文件头记录这些压缩块的偏移量。ui
SequenceFile的核心思想思想差很少如此,数据分块进行组织,块内能够采用压缩的方式。但它在每一个块间设置一个同步标识用于分割块,而没有记录偏移量信息。
Hive诞生之初,就以数仓工具的身份屹立大数据动物圈。而数仓面向的OLAP场景和关系数据库面向的OLTP场景最大的区别就在于:
因此关系数据库一般用B+tree精确索引或者Cache的方式加快查询。
所以按列进行连续存储的方式比按行将数据值串在一块儿连续存储的方式更合适于OLAP场景。
核心缘由在于:
而RCFile正是把列存的思想引入大数据的先驱者,以下图所示。
它的基本思想是将数据水平切分红一个个行组(row group,一般为一个hdfs block大小), 在每一个行组内除了元数据和行组切分标识外,就是按照列值进行一波编码再对全部列进行压缩。
通常而言先驱者下场都不会太好,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很相似,主要的不一样集中在对复杂结构的表示上,这里就不过多介绍了。
自此之后,列存的风吹遍了整个大数据生态圈。
carbondata采用多维排序的方式优化数据的列式布局,druid在列存之上,对维度列采用directory编码加bitmap索引的方式加速了对维度列的筛选和聚合.....
然而存储查询效率远不是大数据所有,实际中的应用问题一样重要。
19年4月,databrick公司平地一声雷,重磅开源的delta lake,给数据添加了acid特性,支持数据的并发读写存储的故事又要拉开一张大幕,世界就是这样精彩。