

# 执行时间旅行和版本旅行查询
<a name="querying-iceberg-time-travel-and-version-travel-queries"></a>

每个 Apache Iceberg 表都维护所包含 Amazon S3 对象的版本控制清单。清单的早期版本可用于时间旅行和版本旅行查询。

Athena 中的时间旅行查询在 Amazon S3 中查询一致快照中截至指定日期和时间的历史数据。Athena 中的版本旅行查询在 Amazon S3 中查询指定快照 ID 以前的历史数据。

## 时间旅行查询
<a name="querying-iceberg-time-travel-queries"></a>

要运行时间旅行查询，请在 `SELECT` 语句中的表名称之后使用 `FOR TIMESTAMP AS OF timestamp`，如下例所示。

```
SELECT * FROM iceberg_table FOR TIMESTAMP AS OF timestamp
```

为旅行指定的系统时间可以是时间戳，也可以是带时区的时间戳。如果未指定，Athena 将该值视为以 UTC 时间表示的时间戳。

以下示例时间旅行查询选择指定日期和时间的 CloudTrail 数据。

```
SELECT * FROM iceberg_table FOR TIMESTAMP AS OF TIMESTAMP '2020-01-01 10:00:00 UTC'
```

```
SELECT * FROM iceberg_table FOR TIMESTAMP AS OF (current_timestamp - interval '1' day)
```

## 版本旅行查询
<a name="querying-iceberg-version-travel-queries"></a>

要执行版本旅行查询（即，查看指定版本以前的一致快照），请在 `SELECT` 语句中的表名称之后使用 `FOR VERSION AS OF version`，如下例所示。

```
SELECT * FROM [db_name.]table_name FOR VERSION AS OF version         
```

*version* 参数是与 Iceberg 表版本关联的 `bigint` 快照 ID。

以下示例版本旅行查询选择指定版本的数据。

```
SELECT * FROM iceberg_table FOR VERSION AS OF 949530903748831860
```

**注意**  
Athena 引擎版本 2 中的 `FOR SYSTEM_TIME AS OF` 和 `FOR SYSTEM_VERSION AS OF` 子句已替换为 Athena 引擎版本 3 中的 `FOR TIMESTAMP AS OF` 和 `FOR VERSION AS OF` 子句。

### 检索快照 ID
<a name="querying-iceberg-table-snapshot-id"></a>

使用 Iceberg 提供的 Java [SnapshotUtil](https://iceberg.apache.org/javadoc/1.6.0/org/apache/iceberg/util/SnapshotUtil.html) 类可以检索 Iceberg 快照 ID，如下例所示。

```
import org.apache.iceberg.Table;
import org.apache.iceberg.aws.glue.GlueCatalog;
import org.apache.iceberg.catalog.TableIdentifier;
import org.apache.iceberg.util.SnapshotUtil;

import java.text.SimpleDateFormat;
import java.util.Date;

Catalog catalog = new GlueCatalog();

Map<String, String> properties = new HashMap<String, String>();
properties.put("warehouse", "s3://amzn-s3-demo-bucket/my-folder");
catalog.initialize("my_catalog", properties);

Date date = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2022/01/01 00:00:00");
long millis = date.getTime();

TableIdentifier name = TableIdentifier.of("db", "table");
Table table = catalog.loadTable(name);
long oldestSnapshotIdAfter2022 = SnapshotUtil.oldestAncestorAfter(table, millis);
```

## 结合使用时间旅行和版本旅行
<a name="querying-iceberg-combining-time-and-version-travel"></a>

您可以在同一查询中使用时间旅行和版本旅行语法来指定不同的时间和版本控制条件，如以下示例所示。

```
SELECT table1.*, table2.* FROM 
  [db_name.]table_name FOR TIMESTAMP AS OF (current_timestamp - interval '1' day) AS table1 
  FULL JOIN 
  [db_name.]table_name FOR VERSION AS OF 5487432386996890161 AS table2 
  ON table1.ts = table2.ts 
  WHERE (table1.id IS NULL OR table2.id IS NULL)
```