

# スキーマの更新を処理する
<a name="handling-schema-updates-chapter"></a>

このセクションでは、さまざまなデータ形式に対するスキーマ更新の処理に関するガイダンスを提供します。Athena はスキーマオンリード (schema-on-read) のクエリエンジンです。これは、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 | はい | 

## Apache ORC と Apache Parquet のインデックスアクセスを理解する
<a name="index-access"></a>

PARQUET および ORC は、インデックス引または名前で読み込み可能な列データストレージ形式です。これらの形式のいずれかでデータを保存すると、スキーマですべてのオペレーションを実行し、スキーマの不一致エラーを生じることなく Athena でクエリを実行できるようになります。
+ Athena は、`SERDEPROPERTIES ( 'orc.column.index.access'='true')` で定義されているように、*デフォルトでインデックスによる ORC* の読み込みを行います。詳細については、「[ORC: インデックスで読み込む](#orc-read-by-index)」を参照してください。
+ Athena は、`SERDEPROPERTIES ( 'parquet.column.index.access'='false')` で定義されているとおり、*デフォルトで名前による Parquet* の読み込みを行います。詳細については、「[Parquet: 名前で読み込む](#parquet-read-by-name)」を参照してください。

これらはデフォルトであるため、これらの SerDe プロパティを `CREATE TABLE` クエリで使用するのはオプションで、暗黙的に使用されます。これらを使用すると、、他のオペレーションを防ぎながら、スキーマの更新オペレーションを実行することができます。これらのオペレーションを有効にするには、別の `CREATE TABLE` クエリを実行し、SerDe の設定を変更します。

**注記**  
SerDe のプロパティは、各パーティションに自動的に伝播*されません*。各パーティションに SerDe プロパティを設定するには、`ALTER TABLE ADD PARTITION` ステートメントを使用します。このプロセスを自動化するには、`ALTER TABLE ADD PARTITION` ステートメントを実行するスクリプトを記述します。

以下のセクションで、これらのケースについて詳しく説明します。

### ORC: インデックスで読み込む
<a name="orc-read-by-index"></a>

ORC 内のテーブルは、*デフォルトでインデックスで読み取られます*。これは、次の構文で定義されます。

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

*インデックスで読み込むと*、列の名前を変更できます。ただし、列の削除やテーブルの中間での追加ができなくなります。

ORC を名前で読み込み、テーブルの中間に列を追加したり、ORC の列を削除したりするには、`orc.column.index.access` ステートメントで、SerDe プロパティ `false` を `CREATE TABLE` に設定します。この設定では、列の名前を変更する機能が失われます。

**注記**  
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` に設定してテーブルを作成する必要があります。