Skip to main content

诡异的Databricks Delta Lake Table History

分类:  Azure Databricks 标签:  #Databricks #大数据 发布于: 2025-02-16 20:00:33

如果大家对于什么是Databricks Delta Lake Table History还不是太清楚,那么你一定要参考Databricks的官方文档: https://docs.databricks.com/en/delta/history.html, 这篇官方文档里详细的描述了什么是Delta LakeTable History, 以及主要支持的场景: Time Travel Query


有一些技术要点可以先在这里总结一下:

  1. 每一个针对Delta Lake表的写操作都会产生一个新的Table History version, 即一个新的commit

  2. 这里所谓的Write操作主要包括这些语句:

    • WRITE

    • CREATE TABLE AS SELECT

    • REPLACE TABLE AS SELECT

    • COPY INTO

    • STREAMING UPDATE

    • DELETE

    • TRUNCATE

    • MERGE

    • UPDATE

    • FSCK

    • CONVERT

    • OPTIMIZE

    • CLONE

    • RESTORE

    • VACUUM

  3. 每个操作以及操作的内容,都一定会产生一个新的历史版本,而且这些历史版本在Delta Lake里使用一种叫做事务日志的机制保存起来,它的保存位置在表目录下的_delta_log目录,每一个新版本的事务日志文件都是一个json文件,注意: 每一个json文件仅仅包含一个写动作。

  4. Delta Lake 默认情况会在每10次提交事务之后生成一个新的checkpoint文件,这个checkpoint文件是一个Parquet文件,它记录所有json文件的内容,主要用于优化查询。这里默认十次提交,可以通过配置delta.checkpointInterval 来更改,默认的表属性配置是10次,这个部分,可以参考Delta 开放的协议说明:https://github.com/delta-io/delta/blob/74d19a5ad2360d358563de27a0b1d90034983439/kernel/kernel-api/src/main/java/io/delta/kernel/internal/TableConfig.java#L74, 如下图:



    1. Delta Table History的所有日志记录称为事务日志,它和用户的数据文件是完全分开存放的。

    2. Time Travel Query 要完成查询同时依赖于事务日志和数据文件。

    3. 事务日志的清理和保存时间由delta Lake自动处理,用户可以配置。

    4. 数据文件的保留时间,用户需要通过命令VACUUM来参与保留和清除。

    以上是Delta Lake Table History的理论总结部分,但是我认为它比较诡异的地方主要就在于Table History可以保留的时长上。

    根据官方的文档描述:

    Table history retention is determined by the table setting delta.logRetentionDuration, which is 30 days by default

    这里描述的非常明确就是可以通过表属性delta.logRetentionDuration 来控制事务日志可以保留的天数来控制Table History可以保留的天数,同时结合Time Travel Query的详细说明:

    To query a previous table version, you must retain both the log and the data files for that version.

    Data files are deleted when VACUUM runs against a table. Delta Lake manages log file removal automatically after checkpointing table versions.

    Because most Delta tables have VACUUM run against them regularly, point-in-time queries should respect the retention threshold for VACUUM, which is 7 days by default.

    In order to increase the data retention threshold for Delta tables, you must configure the following table properties:

    delta.logRetentionDuration = "interval <interval>": controls how long the history for a table is kept. The default is interval 30 days.

    delta.deletedFileRetentionDuration = "interval <interval>": determines the threshold VACUUM uses to remove data files no longer referenced in the current table version. The default is interval 7 days.

    You can specify Delta properties during table creation or set them with an ALTER TABLE statement. See Delta table properties reference.

    这段文字就描述得非常清楚了:

    1. Time Travel 查询同时依赖数据文件的保留时间和事务日志的保留时间,默认情况下数据文件的保留时间是7天,事务日志的保留时间是30天。

    2. 数据文件的保留时间可以通过选项: delta.deletedFileRetentionDuration = "interval <interval>" 配置保留天数

    3. 事务日志文件保留时间可以通过选项: delta.logRetentionDuration = "interval <interval>" 配置保留天数。

    为了验证上述的这个理论,我决定创建如下的表来验证:

    首先是表一, 表参数配置:

    CREATE TABLE test1day (
    Id Integer,
    Name Varchar(50)
    )
    USING delta
    TBLPROPERTIES (
    'delta.logRetentionDuration' = 'interval 1 days',
    'delta.deletedFileRetentionDuration' = "interval 1 days"
    );

    指定该表数据文件保留一天,事务日志保留一天。

    作为对比,同时创建表:

    CREATE TABLE test1sday (
    Id Integer,
    Name Varchar(50)
    )
    USING delta
    TBLPROPERTIES (
    'delta.logRetentionDuration' = 'interval 1 days'
    );

    对照表仅仅指定事务日志保留为一天,但是数据文件保留默认是7天。

    然后经过连续多天的测试, 每天都插入数据,形成新的提交:

    -- 插入数据了. 每天做两次
    insert into testdb1.test1day (Id, Name) values (1, 'test');
    insert into testdb1.test1sday (Id, Name) values (1, 'test');

    然后我们使用DESC History查看多天的table history返回记录:

    2024-8-27:


2024-8-27的截图没有什么好说明的,因为是第一天的测试结果。

然后是第二天:

2024-8-28:


请记得我们对于表一的设置是数据文件一天,事务日志文件一天,表二是事务日志一天,数据文件默认是7天,假设我们认为Databricks runtime有自己的考量,然后多放一天,假假的认为可能是正常的,我们继续看。

2024-8-29:

然后就发现2024-8-29的历史记录完全不知道该怎么形容了,就好像我们的配置在这里根本没起作用。

我故意将这个数据等待20多天之后,也就是2024-9-16, 继续观察:

2024-9-16:

然后我观察更加令人惊悚的一幕:

  1. 表一的数据可能还说得过去,但是9/16和8/29差这么多是什么鬼?

  2. 表二的数据就完全没有办法理解了。。。。

因为这个表现,我和Databricks的工程师做过很多次的讨论,很感谢Databricks工程师给我分享了很多insight, 虽然后来这些insight我都从delta Lake开源的协议中找到了明确的说明,同时也在源代码里找到了印证,但是始终不能说明官方文档里描述的各种特性和明确说明的配置效果。

通过分析Delta Lake协议的源码以及文档,我还是建议大家在使用这个特性的时候,需要仔细的考量使用的场景,从官方的文档反馈以及我测试的结果,我个人发现这个功能还存在一些不确定性,将来未必没有更改的可能性。

注意:这是我个人的建议。