更新タイプ - Amazon Athena

更新タイプ

このトピックでは、実際にデータを変更せずに CREATE TABLE ステートメントのスキーマに加えられるいくつかの変更について説明します。スキーマ更新の各タイプがレビューされ、Athena でこれらの使用が許可されるデータ形式を指定します。スキーマを更新するには、ALTER TABLE コマンドを使用できる場合もあれば、既存のテーブルを実際に変更しない場合もあります。代わりに、元の CREATE TABLE テートメントで使用したスキーマを変更する新しい名前のテーブルを作成します。

期待されるスキーマの進化方法に応じて、Athena クエリの使用を継続するために互換性のあるデータ形式を選択します。

CSV および Parquet の 2 つの形式で存在する orders テーブルからの注文情報を読み取るアプリケーションを考えます。

以下の例では、Parquet でテーブルを作成します。

CREATE EXTERNAL TABLE orders_parquet ( `orderkey` int, `orderstatus` string, `totalprice` double, `orderdate` string, `orderpriority` string, `clerk` string, `shippriority` int ) STORED AS PARQUET LOCATION 's3://DOC-EXAMPLE-BUCKET/orders_ parquet/';

以下の例では、CSV で同じテーブルを作成します。

CREATE EXTERNAL TABLE orders_csv ( `orderkey` int, `orderstatus` string, `totalprice` double, `orderdate` string, `orderpriority` string, `clerk` string, `shippriority` int ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LOCATION 's3://DOC-EXAMPLE-BUCKET/orders_csv/';

以下のセクションでは、これらのテーブルに対する更新がどのように Athena クエリに影響するかを検証します。

テーブルの先頭または中間への列の追加

列の追加は最も頻繁なスキーマの変更の 1 つです。たとえば、新しいデータでテーブルをエンリッチ化するために、新しい列を追加することがあります。または、既存の列のソースが変更された場合に新しい列を追加し、この列の以前のバージョンを保持してそれに依存するアプリケーションを調整することもあります。

テーブルの先頭または中間に列を追加し、既存のテーブルに対してクエリを実行するには、SerDe プロパティが名前で読み取るように設定されている場合は、AVRO、JSON、および Parquet と ORC を使用します。詳細については、Parquet および ORC におけるインデックスアクセス を参照してください。

これらの形式は順序に依存するため、CSV および TSV のテーブルの先頭または中間に列を追加しないでください。このような場合に列を追加すると、パーティションのスキーマが変更されたときにスキーマの不一致エラーが発生します。

次の例では、JSON データに基づいてテーブルの中央に o_comment 列を追加する新しいテーブルを作成します。

CREATE EXTERNAL TABLE orders_json_column_addition ( `o_orderkey` int, `o_custkey` int, `o_orderstatus` string, `o_comment` string, `o_totalprice` double, `o_orderdate` string, `o_orderpriority` string, `o_clerk` string, `o_shippriority` int, ) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' LOCATION 's3://DOC-EXAMPLE-BUCKET/orders_json/';

テーブルの末尾への列の追加

Parquet、ORC、Avro、JSON、CSV、および TSV などの Athena がサポートする形式のいずれかでテーブルを作成する場合は、ALTER TABLE ADD COLUMNS ステートメントを使用して、既存の列の後、かつパーティション列の前の位置に列を追加できます。

次の例では、パーティション comment 列の前の orders_parquet テーブルの末尾に列を追加します。

ALTER TABLE orders_parquet ADD COLUMNS (comment string)
注記

ALTER TABLE ADD COLUMNS を実行した後で Athena クエリエディタに新しいテーブル列を表示するには、エディタのテーブルリストを手動で更新してから、テーブルをもう一度展開します。

列の削除

列に含まれるデータがなくなった場合、あるいは列に含まれているデータへのアクセスを制限する場合に、これらの列を削除する必要があることがあります。

  • 名前で読み込まれている場合、JSON、Avro、および Parquet、ORC でテーブルから列を削除することができます。詳細については、Parquet および ORC におけるインデックスアクセス を参照してください。

  • 既に Athena で作成したテーブルを保持する場合は、CSV および TSV のテーブルから列を削除することは推奨されません。列を削除するとスキーマが壊れ、削除された列がない状態でテーブルを再作成しなければならなくなります。

この例では、Parquet のテーブルから `totalprice` 列を削除して、クエリを実行します。Athena では、デフォルトで Parquet の読み取りが名前で行われます。名前での読み取りを指定する SERDEPROPERTIES 設定が省略されているのはこのためです。スキーマを変更しても、次のクエリは成功することに注意してください。

CREATE EXTERNAL TABLE orders_parquet_column_removed ( `o_orderkey` int, `o_custkey` int, `o_orderstatus` string, `o_orderdate` string, `o_orderpriority` string, `o_clerk` string, `o_shippriority` int, `o_comment` string ) STORED AS PARQUET LOCATION 's3://DOC-EXAMPLE-BUCKET/orders_parquet/';

列名の変更

綴りを修正する、列名をより分かりやすくする、または列の順序変更を回避するために、テーブルで列の名前変更が必要となる場合があります。

データを CSV および TSV に保存する場合は列の名前を変更できます。また、インデックスで読み取るように設定されている場合は、Parquet および ORC に保存できます。詳細については、Parquet および ORC におけるインデックスアクセス を参照してください。

Athena は CSV と TSV のデータをスキーマの列順に読み取り、それらを同じ順序で返します。Athena は、列にデータをマップするために列名を使用しません。Athena クエリを破損することなく CSV または TSV で列名を変更できるのはこのためです。

列名を変更する戦略の 1 つは、同じ基盤データに基づく新しいテーブルを、新しい列名を使用して作成することです。以下の例は、orders_parquet_column_renamed という名前の新しい orders_parquet テーブルを作成します。この例は、列 `o_totalprice` の名前を `o_total_price` に変更してから、Athena でクエリを実行します。

CREATE EXTERNAL TABLE orders_parquet_column_renamed ( `o_orderkey` int, `o_custkey` int, `o_orderstatus` string, `o_total_price` double, `o_orderdate` string, `o_orderpriority` string, `o_clerk` string, `o_shippriority` int, `o_comment` string ) STORED AS PARQUET LOCATION 's3://DOC-EXAMPLE-BUCKET/orders_parquet/';

Parquet テーブルの場合、次のクエリは実行されますが、列がインデックスではなく名前でアクセスされているため (Parquet のデフォルト)、名前が変更された列にはデータが表示されません。

SELECT * FROM orders_parquet_column_renamed;

CSV のテーブルでのクエリも類似しています。

CREATE EXTERNAL TABLE orders_csv_column_renamed ( `o_orderkey` int, `o_custkey` int, `o_orderstatus` string, `o_total_price` double, `o_orderdate` string, `o_orderpriority` string, `o_clerk` string, `o_shippriority` int, `o_comment` string ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LOCATION 's3://DOC-EXAMPLE-BUCKET/orders_csv/';

CSV テーブルの場合、次のクエリを実行すると、名前が変更された列を含むすべての列でデータが表示されます。

SELECT * FROM orders_csv_column_renamed;

列の順序の変更

デフォルトで名前で読み取る JSON や Parquet など、名前で読み取る形式のデータを含むテーブルの列の順序を変更できます。必要に応じて、ORC を名前で読み取ることもできます。詳細については、Parquet および ORC におけるインデックスアクセス を参照してください。

次の例では、列の順序が違う新しいテーブルを作成します。

CREATE EXTERNAL TABLE orders_parquet_columns_reordered ( `o_comment` string, `o_orderkey` int, `o_custkey` int, `o_orderpriority` string, `o_orderstatus` string, `o_clerk` string, `o_shippriority` int, `o_orderdate` string ) STORED AS PARQUET LOCATION 's3://DOC-EXAMPLE-BUCKET/orders_parquet/';

列のデータ型の変更

既存のタイプでは必要な量の情報を保持できなくなった場合は、別の列タイプを使用することをお勧めします。例えば、ID 列の値が INT データ型のサイズを超えているため、その BIGINT データ型を使用する必要があります。

列に別のデータ型を使用するときは、以下の点を考慮してください。

  • ほとんどの場合、列のデータ型を直接変更することはできません。代わりに、Athena テーブルを再作成し、新しいデータ型で列を定義します。

  • 一部のデータ型のみを他のデータ型として読み取ることができます。扱えるデータ型については、このセクションの表を参照してください。

  • Parquet および ORC のデータでは、テーブルがパーティション分割されていない場合、列に異なるデータ型を使用することはできません。

  • Parquet および ORC のパーティション分割されたテーブルでは、パーティションの列タイプが別のパーティションの列タイプと異なる場合があり、可能な場合は、Athena が望ましいタイプに CAST します。詳細については、パーティションがあるテーブルに対するスキーマの不一致エラーの回避 を参照してください。

  • LazySimpleSerDE のみを使用して作成されたテーブルでは、ALTER TABLE REPLACE COLUMNS ステートメントを使用して既存の列を別のデータ型に置き換えることができますが、保持したい既存の列もすべてステートメントに再定義する必要があります。これを行わないと、削除されます。詳細については、「ALTER TABLE REPLACE COLUMNS」を参照してください。

  • Apache Iceberg テーブルの場合のみ、ALTER TABLE CHANGE COLUMN ステートメントを使用して列のデータ型を変更できます。 ALTER TABLE REPLACE COLUMNS は Iceberg テーブルではサポートされていません。詳細については、「Iceberg テーブルスキーマの進化」を参照してください。

重要

データ型の変換を実行する前に、クエリをテストして検証することを強くお勧めします。Athena がターゲットのデータ型を使用できない場合、CREATE TABLE クエリは失敗する可能性があります。

次の表は、他のデータ型として扱われるデータ型の一覧です。

互換性のあるデータ型
元のデータ型 使用可能なターゲットデータ型
STRING BYTE, TINYINT, SMALLINT, INT, BIGINT
BYTE TINYINT, SMALLINT, INT, BIGINT
TINYINT SMALLINT, INT, BIGINT
SMALLINT INT, BIGINT
INT BIGINT
FLOAT DOUBLE

次の例では、元の orders_json テーブルの CREATE TABLE ステートメントを使用して、orders_json_bigint という新しいテーブルを作成します。新しいテーブルでは、`o_shippriority` 列のデータ型として INT の代わりに BIGINT が使用されます。

CREATE EXTERNAL TABLE orders_json_bigint ( `o_orderkey` int, `o_custkey` int, `o_orderstatus` string, `o_totalprice` double, `o_orderdate` string, `o_orderpriority` string, `o_clerk` string, `o_shippriority` BIGINT ) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' LOCATION 's3://DOC-EXAMPLE-BUCKET/orders_json';

次のクエリは、元の SELECT クエリと同様に、データ型が変更される前に正常に実行されます。

Select * from orders_json LIMIT 10;