

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 使用時間戳記資料
<a name="data-types-timestamps"></a>

本節說明在 Athena 中使用時間戳記資料的一些考量。

**注意**  
先前的引擎版本與 Athena 引擎版本 3 之間的時間戳記處理方式發生變更。如需有關 Athena 引擎版本 3 中可能發生的時間戳記相關錯誤及建議的解決方案的資訊，請參閱 [Athena 引擎版本 3](engine-versions-reference-0003.md) 參考中的 [時間戳記變更](engine-versions-reference-0003.md#engine-versions-reference-0003-timestamp-changes)。

## 將時間戳記資料寫入 Amazon S3 物件的格式
<a name="data-types-timestamps-writing-to-s3-objects"></a>

將時間戳記資料寫入 Amazon S3 物件的格式，取決於您使用的資料欄資料類型和 [SerDe 程式庫](https://docs.aws.amazon.com/athena/latest/ug/supported-serdes.html)。
+ 如果您有類型為 `DATE` 的資料表資料欄，Athena 會預期資料的對應資料欄或屬性是 ISO 格式的字串 `YYYY-MM-DD`，或是內建的日期類型 (例如 Parquet 或 ORC 的日期類型)。
+ 如果您有類型為 `TIME` 的資料表資料欄，Athena 會預期資料的對應資料欄或屬性是 ISO 格式的字串 `HH:MM:SS`，或是內建的時間類型 (例如 Parquet 或 ORC 的時間類型)。
+ 如果您有類型為 `TIMESTAMP` 的資料表資料欄，Athena 會預期資料的對應資料欄或屬性是格式的字串 `YYYY-MM-DD HH:MM:SS.SSS` (注意日期和時間之間的空格)，或是內建的時間類型 (例如 Parquet、ORC 或 Ion 的時間類型)。請注意，Athena 不保證對無效時間戳記的行為 （例如 `0000-00-00 08:00:00.000`)。
**注意**  
OpenCSVSerDe 時間戳記是例外狀況，且必須編碼為毫秒解析度的 UNIX epochs。

## 確保時間分割資料符合記錄中的時間戳記欄位
<a name="data-types-timestamps-time-partitioned-data-and-timestamp-fields"></a>

資料的產生者必須確定分割區值與分割區內的資料一致。例如，如果您的資料具有 `timestamp` 屬性，而您使用 Firehose 將資料載入 Amazon S3，則必須使用[動態分割](https://docs.aws.amazon.com/firehose/latest/dev/dynamic-partitioning.html)，因為 Firehose 的預設分割以掛鐘為基礎的。

## 使用字串做為分割區索引鍵的資料類型
<a name="data-types-timestamps-partition-key-types"></a>

出於效能考量，最好將 `STRING` 用作分割區索引鍵的資料類型。雖然 Athena 將格式 `YYYY-MM-DD` 的分割區值識別為您使用 `DATE` 類型時的日期，而這可能造成效能不彰。因此，我們建議您改用 `STRING` 資料類型做為分割區索引鍵。

## 如何寫入同樣按時間分割的時間戳記欄位的查詢
<a name="data-types-timestamps-how-to-write-queries-for-timestamp-fields-that-are-also-time-partitioned"></a>

如何寫入同樣按時間分割的時間戳記欄位的查詢，取決於您要查詢的資料表的類型。

### Hive 資料表
<a name="data-types-timestamps-hive-tables"></a>

使用 Athena 中最常用的 Hive 資料表，查詢引擎對資料欄和分割區索引鍵之間的關係一無所知。因此，您必須始終在資料欄和分割區索引鍵的查詢中新增述詞。

例如，假設您有 `event_time` 資料欄和 `event_date` 分割區索引鍵，而且想要查詢 23:00 到 03:00 之間的事件。在此案例中，您必須在查詢資料欄和分割區索引鍵中包含述詞，如下列範例所示。

```
WHERE event_time BETWEEN start_time AND end_time 
  AND event_date BETWEEN start_time_date AND end_time_date
```

### Iceberg 資料表
<a name="data-types-timestamps-iceberg-tables"></a>

使用 Iceberg 資料表，您可以使用運算的分割區值，從而簡化查詢。例如，假設您的 Iceberg 資料表是使用如下 `PARTITIONED BY` 子句建立的：

```
PARTITIONED BY (event_date month(event_time))
```

在此案例下，查詢引擎會根據 `event_time` 述詞的值自動剔除分割區。因此，您的查詢只需要指定 `event_time` 的述詞，如下列範例所示。

```
WHERE event_time BETWEEN start_time AND end_time
```

如需詳細資訊，請參閱[建立 Iceberg 資料表](querying-iceberg-creating-tables.md)。

對時間戳記資料欄使用 Iceberg 的隱藏分割時，Iceberg 可能會在衍生自時間戳記資料欄的建構資料表資料欄上建立分割區，並將其轉換為日期，以實現更有效的分割。例如，它可能會從時間戳記資料欄 `event_time` 建立 `event_date`，並在 `event_date` 上自動進行分割。在這種情況下，分割區**類型**是**日期**。

為了在使用分割區時獲得最佳查詢效能，請篩選全天範圍以啟用述詞下推。例如，下列查詢不會下推，因為範圍無法轉換為單一日期分割區，即使其恰到落在一天內：

```
WHERE event_time >= TIMESTAMP '2024-04-18 00:00:00' AND event_time < TIMESTAMP '2024-04-18 12:00:00'
```

相反地，請使用全天範圍來允許述詞下推，並提升查詢效能，如下列範例所示。

```
WHERE event_time >= TIMESTAMP '2024-04-18 00:00:00' AND event_time < TIMESTAMP '2024-04-19 00:00:00'
```

您也可以使用 `BETWEEN start_time AND end_time` 語法或使用多日範圍，只要時間戳記部分為 `00:00:00` 即可。

如需詳細資訊，請參閱 [Trino 部落格文章](https://trino.io/blog/2023/04/11/date-predicates.html)。