时间旅行
Iceberg表格式支持的另一个关键功能是所谓的“时间旅行”。Iceberg提供了开箱即用的功能,可以查看一个表在过去不同时间点的样子。
为了选择特定的表快照或某个时间点的快照,Iceberg支持两个Spark读选项:
- (1) snapshot-id:选择一个特定的表快照。
- (2) as-of-timestamp:选择某个时间戳(以毫秒为单位)的当前快照。
用户可以查看某个表的snapshots快照元数据表来查看该表的快照信息。例如,要查看hadoop_prod.my_db.phones表的所有快照,代码如下:
// 查看所有的快照
spark.sql("select * from hadoop_prod.my_db.phones.snapshots").show()
可以得到的输出信息如图11-36所示。
可以只选取部分字段以查看完整的提交时间,代码如下:
spark.sql("select * from hadoop_prod.my_db.phones.snapshots")
.select("committed_at","snapshot_id","parent_id","operation")
.show(false)
执行上面的代码,输出内容如图11-37所示。
其中snapshot_id字段代表每个快照版本编号,committed_at字段代表该版本快照的提交时间。
如果想要查看指定版本或时间点的表内容(即所谓的时间旅行),可以使用“as-of-timestamp”选项。例如,指定查看2022-03-14 19:00:25这是时刻的表的内容,可以执行时间旅行,代码如下:
// 时间旅行到 2022-03-14 19:00:25
import java.sql.Timestamp
spark.read
.option("as-of-timestamp", Timestamp.valueOf("2022-03-14 19:00:25").getTime())
.format("iceberg")
.load("hadoop_prod.my_db.phones")
.show()
执行以上代码,可以得到如下的输出内容:
+-----+-------+-----+ | id| price|stock| +-----+-------+-----+ | oppo|1688.00| 230| | noov| 499.00| 310| |Nokia| 699.00| 350| | vivo|2199.00| 120| | 华为|2299.00| 200| | 小米|1199.00| 100| | 苹果|2799.00| 150| +-----+-------+-----+
如果再旅行到时间点2022-03-14 18:52:25,查看这个时刻表中的内容,代码如下:
// 时间旅行到 2022-03-14 18:52:25
import java.sql.Timestamp
spark.read
.option("as-of-timestamp", Timestamp.valueOf("2022-03-14 18:52:25").getTime())
.format("iceberg")
.load("hadoop_prod.my_db.phones")
.show()
则可以得到如下这样的输出内容:
+-----+-------+-----+ | id| price|stock| +-----+-------+-----+ | oppo|1688.00| 230| | noov| 499.00| 310| | 小米|1299.00| 100| | 苹果|3299.00| 300| | 华为|2299.00| 200| |Nokia| 699.00| 350| +-----+-------+-----+
也可以通过“snapshot-id”选项查看指定快照版本对应的表内容。例如,要查看snapshot-id为ID为7625222922103268949的快照对应的表内容,代码如下:
// 时间旅行到ID为7625222922103268949L的快照
spark.read
.option("snapshot-id", 6959645350842185769L)
.format("iceberg")
.load("hadoop_prod.my_db.phones")
.show()
执行上面的代码,可以得到如下的输出内容:
+-----+-------+-----+ | id| price|stock| +-----+-------+-----+ | 小米|1299.00| 100| | 苹果|3299.00| 300| | 华为|2299.00| 200| |Nokia| 699.00| 350| +-----+-------+-----+
如果再时间旅行到ID为8262259194646368185的快照,查看此时的表内容,代码如下:
// 时间旅行到ID为8262259194646368185L的快照
spark.read
.option("snapshot-id", 7048516951834814451L)
.format("iceberg")
.load("hadoop_prod.my_db.phones")
.show()
执行以上代码,则可以得到的表内容如下:
+-----+-------+-----+ | id| price|stock| +-----+-------+-----+ | oppo|1688.00| 230| | noov| 499.00| 310| | 小米|1299.00| 100| | 苹果|3299.00| 300| | 华为|2299.00| 200| |Nokia| 699.00| 350| +-----+-------+-----+
注意: Spark目前不支持在DataFrameReader命令中使用带有option的table()方法,所有option选项将被无声地忽略。当尝试时间旅行或使用其他选项时,不要使用table。Options选项将在Spark 3.1 - Spark-32592中支持table。
注意: Spark的SQL语法还不支持时间旅行。