前缘
Delta刚开源的时候我就去使用了一把,然后因为刚开源,很多功能还是缺失的,比如很重要的upsert/compaction 等。于是我就开发了
开发的过程中,我熟悉了下delta的源码,为其设计的精妙不禁感叹不已。Delta的核心设计非常非常简单,但是这总简单的解法却能有效的解决很多问题。大家可以想想以前在高中的时候做数据证明题,好的解法又简单,又容易理解,而且天生自带美感,让人觉得就像在欣赏一幅字画,把玩中内心享受到了美的熏陶。
简单的设计
Delta 并没有自己发明一种新文件存储格式,而是复用了parquet,但是parquet只是一个带格式的文件而已,而且是面向查询设计的存储格式,对文件里面的记录是无法进行删除,更新动作的。那现在我们要实现一堆的特性,如更新,删除,新增,覆盖,流写,批写,版本回溯等等,该怎么办呢?
Delta 巧妙的将上述动作抽象成了无论你做什么操作,本质上都是新增文件,删除文件(标记删除)。 再解释一把就是,parquet文件为最基本的操作粒度,我们需要将前面提到的更新,删除,新增,覆盖,流批写,版本回溯等等都最终抽象成两个动作:
那是不是这个抽象真的能够实现这些功能呢?实际实践后发现是完全可以的。为了能够知道某一次到底新增了几个文件,标记删除了几个文件,我们需要有一个地方记录,这个地方就是meta文件目录,在该目录里,我们使用json格式,记录某次批、流写新增了哪些文件,删除了哪些文件。
别看就这么简单的做法,基本上就把我们前面要的功能就都实现了,假设我们对delta一共操作了三次分别产生a,b,c三个json文件,现在,我可以回溯到这三次中任何一次的状态。比如c其实是一次错误操作,我想回退一下,这个时候我只要读a,b两个文件,我就知道当前有哪些parquet文件是有效的,从而读取到正确的数据。虽然数据目录里已经有c写的parquet文件了,但是我系统不读取它,就相当于c没有发生过。这里就完成版本回溯的功能。
我们会在后续章节解释delta到底是如何实现更新等功能的细节的。但是这里大家只要了解,delta的所有操作功能,都可以理解为新增文件,标记删除文件,以及将这些操作信息记录下来。
所以有人会说,delta不过是在parquet之上加了一个操作记录功能而已,实际上确实如此。