

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

# 處理結構描述更新
<a name="handling-schema-updates-chapter"></a>

本節指導處理各種資料格式的結構描述更新。Athena 是一種讀取時定義結構描述的查詢引擎。這表示當您在 Athena 中建立資料表時，將於讀取資料時套用結構描述。並不會變更或重寫基礎資料。

如果您預期資料表結構描述會變更，請考慮以符合您需要的資料格式建立結構描述。您的目標是隨著不斷演變的結構描述而重複使用現有的 Athena 查詢，並避免在查詢含有分割區的資料表時，發生結構描述不符的錯誤。

為了達到這些目標，請根據下列主題中的表格來選擇資料表的資料格式。

**Topics**
+ [資料格式支援的結構描述更新操作](#summary-of-updates)
+ [了解 Apache ORC 和 Apache Parquet 的索引存取](#index-access)
+ [進行結構描述更新](make-schema-updates.md)
+ [更新含有分割區的資料表](updates-and-partitions.md)

## 資料格式支援的結構描述更新操作
<a name="summary-of-updates"></a>

下表彙總資料儲存格式及其支援的結構描述操作。使用此資料表協助您選擇格式，即使結構描述隨著時間而變更，此格式也能讓您繼續使用 Athena 查詢。

在此表格中，請注意 Parquet 和 ORC 是單欄式格式，具有不同的預設欄存取方法。在預設情況下，Parquet 依名稱存取欄，而 ORC 依索引 (序數值) 存取欄。因此，Athena 提供建立資料表時定義的 SerDe 屬性，以切換預設資料欄存取方法，順應結構描述演變而能有更大的靈活性。

對於 Parquet，`parquet.column.index.access` 屬性可以設為 `true`，以設定資料欄存取方法來使用資料欄的序號。將此屬性設為 `false` 會變更欄存取方法來使用欄名稱。同樣地，對於 ORC，請使用 `orc.column.index.access` 屬性來控制欄存取方法。如需詳細資訊，請參閱[了解 Apache ORC 和 Apache Parquet 的索引存取](#index-access)。

CSV 和 TSV 可讓您執行所有結構描述操作，但不包括重新排序欄，或在資料表開頭新增欄。例如，如果您的結構描述演變只需要重新命名欄，而不需要移除欄，則您可以選擇以 CSV 或 TSV 建立資料表。如果您需要移除欄，請勿使用 CSV 或 TSV，而應該使用任何其他支援的格式，最好是單欄格式，例如 Parquet 或 ORC。


**Athena 中的結構描述更新和資料格式**  

| 預期的結構描述更新類型 | 摘要 | CSV (具有和沒有標頭) 和 TSV | JSON | AVRO | PARQUET：依名稱讀取 (預設) | PARQUET：依索引讀取 | ORC：依索引讀取 (預設) | ORC：依名稱讀取 | 
| --- | --- | --- | --- | --- | --- | --- | --- | --- | 
|  [重新命名欄](updates-renaming-columns.md) | 以 CSV 和 TSV 存放資料，或如果是依索引讀取資料，請以 ORC 和 Parquet 存放資料。 | Y | N | N | N  | Y | Y | N | 
|  [在資料表開頭或中間新增欄](updates-add-columns-beginning-middle-of-table.md) | 以 JSON、AVRO 存放資料，或如果是依名稱讀取資料，請以 Parquet 和 ORC 存放資料。請勿使用 CSV 和 TSV。 | N | Y | Y | Y | N | N | Y | 
|  [在資料表尾端新增欄](updates-add-columns-end-of-table.md) | 以 CSV 或 TSV、JSON、AVRO、ORC 或 Parquet 存放您的資料。 | Y | Y | Y | Y | Y | Y | Y | 
| [移除欄](updates-removing-columns.md) |  如果是依名稱讀取資料，請以 JSON、AVRO 或 Parquet 和 ORC 存放資料。請勿使用 CSV 和 TSV。 | N | Y | Y | Y | N | N | Y | 
| [重新排序欄](updates-reordering-columns.md) | 如果是依名稱讀取資料，請以 AVRO、JSON 或 ORC 和 Parquet 存放資料。 | N | Y | Y | Y | N | N | Y | 
| [變更欄的資料類型](updates-changing-column-type.md) | 以任何格式存放資料，但在 Athena 中測試您的查詢，以確保資料類型相容。對於 Parquet 和 ORC，變更資料類型僅適用於分割資料表。 | Y | Y | Y | Y | Y | Y | Y | 

## 了解 Apache ORC 和 Apache Parquet 的索引存取
<a name="index-access"></a>

PARQUET 和 ORC 是可依索引或依名稱讀取的單欄資料儲存格式。以這些格式存放資料可讓您對結構描述執行所有操作和執行 Athena 查詢，而不會發生結構描述不符的錯誤。
+ Athena 根據預設*依索引讀取 ORC*，如 `SERDEPROPERTIES ( 'orc.column.index.access'='true')` 中所定義。如需詳細資訊，請參閱[ORC：依索引讀取](#orc-read-by-index)。
+ Athena *根據預設依名稱讀取 Parquet*，如 `SERDEPROPERTIES ( 'parquet.column.index.access'='false')` 中所定義。如需詳細資訊，請參閱[Parquet：依名稱讀取](#parquet-read-by-name)。

由於這些是預設值，在 `CREATE TABLE` 查詢中指定這些 SerDe 屬性是選擇性，且隱含地使用。使用時可讓您執行一些結構描述更新操作，同時會防止其他這類操作。若要啟用這些操作，請執行另一個 `CREATE TABLE` 查詢並變更 SerDe 設定。

**注意**  
SerDe 屬性並*不會*自動傳播到每個分割區。使用 `ALTER TABLE ADD PARTITION` 陳述式設定每個分割區的 SerDe 屬性。若要讓這個程序自動化，請編寫可執行 `ALTER TABLE ADD PARTITION` 陳述式的指令碼。

下列各節詳細說明這些案例。

### ORC：依索引讀取
<a name="orc-read-by-index"></a>

預設會*依索引讀取 ORC 資料表*。這是由下列語法所定義：

```
{{WITH SERDEPROPERTIES ( 
  'orc.column.index.access'='true')}}
```

*依索引讀取*可讓您重新命名欄。但之後您就無法在資料表中間移除欄或新增欄。

若要讓 ORC 依名稱讀取，以允許您在資料表中間以 ORC 新增欄或移除欄，請在 `CREATE TABLE` 陳述式中將 SerDe 屬性 `orc.column.index.access` 設為 `false`。在此組態中，您將無法重新命名欄。

**注意**  
在 Athena 引擎版本 2 中，當 ORC 資料表設定為依名稱讀取時，Athena 會要求 ORC 檔案中的所有資料欄名稱都為小寫字母。Apache Spark 在產生 ORC 檔案時不會以小寫字母顯示欄位名稱，所以 Athena 可能無法讀取所產生的資料。解決方法是重新以小寫字母命名資料欄，或使用 Athena 引擎版本 3。

以下範例說明如何將 ORC 變更為依名稱讀取：

```
CREATE EXTERNAL TABLE orders_orc_read_by_name (
   `o_comment` string,
   `o_orderkey` int, 
   `o_custkey` int, 
   `o_orderpriority` string, 
   `o_orderstatus` string, 
   `o_clerk` string, 
   `o_shippriority` int, 
   `o_orderdate` string
) 
ROW FORMAT SERDE 
  'org.apache.hadoop.hive.ql.io.orc.OrcSerde' 
{{WITH SERDEPROPERTIES ( 
  'orc.column.index.access'='false')}} 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.orc.OrcInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat'
LOCATION 's3://amzn-s3-demo-bucket/orders_orc/';
```

### Parquet：依名稱讀取
<a name="parquet-read-by-name"></a>

預設會*依名稱讀取 Parquet 資料表*。這是由下列語法所定義：

```
{{WITH SERDEPROPERTIES ( 
  'parquet.column.index.access'='false')}}
```

*依名稱讀取*可讓您在資料表中間新增欄及移除欄。但之後您就無法重新命欄。

若要讓 Parquet 依索引讀取，以允許您重新命名欄，您建立資料表時必須將 `parquet.column.index.access` SerDe 屬性設為 `true`。