发布日期:2022-10-26 VIP内容

时间旅行

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语法还不支持时间旅行。