Sequence Number In Iceberg
date
slug
tags
summary
type
status
为什么需要sequence number
Iceberg V2版本引入了DeleteFile功能,增强了merge-on-read的支持。在DeleteFile中,将记录需要删除数据行的具体位置(position delete file)或相应的键值(equality delete file)。这样,在进行数据读取时,系统可以依据DeleteFile中的信息过滤掉相应的数据行。
实现这一机制的一个关键点在于确定数据读取时哪些DeleteFile应当被应用。
Iceberg在处理数据文件(Data File)和删除文件(Delete File)时,采用了序列号(Sequence Number)机制来标记它们的创建顺序。这里的序列号越大,表示文件是在更晚的时间点被创建。根据这个规则,一个删除文件(Delete File)只会对那些序列号小于它自己的数据文件产生影响,即只有在删除文件创建之前存在的数据文件会受到删除操作的影响。具体规则可见spec。
每当发生数据变化,比如添加、删除或更新数据时,Iceberg 会创建一个新的快照来表示这些变化。每个快照都被分配一个新的sequence number(该sequence number保证会比过去分配的大以满足递增的性质)。对于在该快照新添加的文件(快照也可能包含已存在的文件),最终会被设置为新的sequence number。
最终会被设置是指:对于manifest文件,sequence number并不会在写过程设置,而是在读过程设置(spec中的inherit)。后文会解释这么做的原因。
Sequence number的设置规则
Iceberg metadata包含的sequence number的field的设置规则
Manifest Entry: - sequence_number: Data sequence number of the file. Inherited when null and status is 1 (added). - file_sequence_number: File sequence number indicating when the file was added. Inherited when null and status is 1 (added) ref: https://iceberg.apache.org/spec/#manifests
- 当entry是新增时,sequence_number和file_sequence_number都被设置成null,在读的时候继承当前snapshot的sequence number
- 当entry是0 (existing) or 2 (deleted),应该将sequence_number和file_sequence_number设置成和原来一样
If the entry status is 0 (existing) or 2 (deleted), the entry must include both sequence numbers explicitly.
- 当entry是新增,但内容属于在过去创建时,这种case我的理解应该是比如合并文件?sequence number保持和原来一样,file sequence number设置为null,在读的时候继承当前snapshot的sequence number。
从上面的规则可以看到,sequence number才是数据被创建时的次序,file sequence number的引入应该是为了第3种case,因此spec中也提到了删除规则会根据sequence number作用而不是file sequence number。
Manifest(ManifestList Entry): - sequence_number: The sequence number when the manifest was added to the table; use 0 when reading v1 manifest lists - min_sequence_number: The minimum data sequence number of all live data or delete files in the manifest; use 0 when reading v1 manifest lists ref: https://iceberg.apache.org/spec/#manifest-lists
当manifest是新增的,sequence number应该设置为当前snapshot的sequence number表示该manifest是当前快照新增的。
对于min sequence number:
- 若新增的manifest中可能包含过去的数据,比如以上的第2(existing),3种情况,则min_sequence_number应该设置为对应Manifest Entry的sequence number。
- 否则min_sequence_number设置为当前sequence number
在读取时,min sequence number用于在读过程中过滤出有效的delete file,比如manifest file的min sequence number是2,则能够作用于该manifest file的delete file必须包含≥2的sequence number。
Why Inheritance
对于sequence number的设置,iceberg并不是在写的时候第一时间设置,而是在读的时候才将null替换到对应snapshot到sequence number,spec中称为Inheritance。
对于这么做的原因,spec中其实提到了:
Inheriting sequence numbers through the metadata tree allows writing a new manifest without a known sequence number, so that a manifest can be written once and reused in commit retries. To change a sequence number for a retry, only the manifest list must be rewritten.
在Iceberg中,为了支持可序列化的隔离级别,采用了原子性的提交机制。然而,有时候提交可能会失败,这就需要进行重新提交。在这个过程中,关键的一步是生成一个新的sequence number,因为在重试期间,可能已经有其他提交发生。如果我们直接将序列号写入到每个manifest中,那么每次重新提交时,所有的manifest都需要更新序列号并重新写入,这是一个耗时的过程。
Iceberg通过inheritance机制优雅地解决了这个问题。在这种方式下,sequence number只直接写入到manifest list中。因此,如果提交失败,只需重写manifest list即可。由于每个snapshot仅关联一个manifest list,所以重写的成本相对较低。
Loading...