なになれ

IT系のことを記録していきます

分かりにくいAmazon Athenaでのデータ型の変更方法をまとめる

背景

Amazon Athenaにおいて、既存テーブルのカラムのデータ型を変更する場合、単純に変更できないことがあります。
本内容では、Athenaにおけるデータ型の変更方法について説明します。
また、データの形式としてParquetでデータを扱っていることを前提とします。

概要

AthenaではGlueのデータカタログとS3の実データを利用しています。
データ型を変更するためのポイントは以下の通りです。

AthenaでParquet形式のデータを扱う場合、データカタログのデータ型を変更しただけだとエラーになってしまいます。
Parquet形式のデータはデータ内でデータ型を持っていて、実データとデータ型が異なるためにエラーになります。

ちなみに、JSON形式のデータではエラーになりません。JSONでは厳密にデータ型を持っていないからと思われます。
JSON形式の場合、データカタログのデータ型を変更し、パーティションを再作成することでデータ型を変更できます。

データ型の変更方法

手順に沿って、各内容を説明します。

S3上の実データのデータ型を変更する

実データのデータ型を変更します。データ作成には、いくつか方法があると思いますが、今回はAthenaのCTASを使用します。
クエリでCAST関数を使用して、データ型を変更します。
ここでは、cast(request_processing_time as varchar)で文字列型に変更して、データを作成します。
また、既存のテーブルからデータ型を変更したテーブルをCREATEするようにします。
これ以降で、本手順で作成したデータのみを利用するためです。

CREATE TABLE default.sample_tmp WITH (
  format = 'parquet',
  parquet_compression = 'SNAPPY',
  external_location = 's3://hi1280-log/sample/123456789012/elasticloadbalancing/ap-northeast-1/',
  partitioned_by = ARRAY ['year', 'month', 'day']
) AS
SELECT
  cast(request_processing_time as varchar) as request_processing_time
  ,year
  ,month
  ,day
FROM
  default.sample

明示的にCAST関数でデータ型を指定しない場合、データの内容に応じてデータ型が決まります。
整数のデータしかない状態だと、int型になってしまうため、CASTが必要になります。

GlueデータカタログのAPIを使って、データ型を変更する

AWS CLIを使う場合、ColumnsのTypeを変更することで、データ型を変更します。
また、Locationの指定で、前手順で作成したデータの配置先を指定するように変更します。

$ aws glue update-table --database-name default --table-input file://table.json

table.json

{
"Name": "sample",
...
  "StorageDescriptor": {
    "Columns": [
      {
        "Name": "request_processing_time",
        "Type": "string"
      },
...
    ],
    "Location": "s3://hi1280-log/sample/123456789012/elasticloadbalancing/ap-northeast-1/",
...
  },
...
}

桁数を含むデータ型の変更を行う場合には、APIを介してデータ型を変更する必要があります。
マネージドコンソールから変更する場合、decimal(8,1)といったデータ桁数を含めたデータ型の変更はできないようになっています。

パーティションがある場合)パーティションを再作成する

パーティションのデータ内には、データ型の情報が存在しています。
既存のパーティションは古いデータ型になっており、そのままAthenaで操作すると該当のパーティションのデータを参照する際にデータ型が異なり、エラーとなってしまいます。
そのため、新しいデータ型に合わせて、パーティションを再作成する必要があります。

パーティションを再作成する際の手順としては以下のとおりです。

既存のテーブルを削除します。

$ aws glue delete-table --database-name default --name sample

これはデータカタログを削除するコマンドなので、S3上の実データは存在します。

再度同じテーブルを作成します。これによって、パーティションが存在しない状態のテーブルを用意します。

$ aws glue create-table --database-name default --table-input file://table.json

AthenaのMSCK REPAIR TABLEクエリで全パーティションを作り直します。

$ aws athena start-query-execution --query-string "MSCK REPAIR TABLE default.sample"

1000くらいのパーティション数であれば、数分で完了します。パーティションの数が多いとかなり時間がかかります。

まとめ

Athenaでのデータ型の変更においては、データカタログとS3上の実データという2つのリソースでデータ型を意識する必要があり、ハマりどころでした。
このあたりを意識できるとスムーズにデータ型の変更ができると思います。