Amazon Athena で no viable alternative at input への対処法


背景

以前からあるCloudTrailのログをAthenaで分析したいと思いクエリを投げましたが、クエリが重いのでなんとかしたいと思いました。

Partitionを分割して時間とコストを節約しようと考え、Athenaのテーブルを作成しなおそうと思ったら、no viable alternative at input 'create external' のようなエラーに遭遇。

Syntaxがおかしいっぽいことまではわかるのだけど、これだけじゃどこを直して良いのかわからない。。。

とりあえず、公式ドキュメントを確認。さすがよくまとまってます。

DDL確認ポイント

公式ドキュメントから、確認ポイントを抜粋しました。
これらをひとつひとつチェックしていけば、ほぼ間違いなくエラーは消えるでしょう。

  • テーブル名に特殊文字(アンダースコア(_)以外)を使ってる
  • テーブル名を数値から始めている
  • カラム名に特殊文字(アンダースコア(_)以外)を使ってる
  • カラム名をクォートで囲っている
  • 括弧が足りない
  • アンダースコアから始まる名前がバックスラッシュで囲ってない
  • カンマが欠落している
  • 半角スペースが足りない
  • カラムやパーティション指定時に、最後のカンマが余計についている
  • パーティションのカラム名に、テーブルのカラム名と同じものが指定されている

テーブル名にハイフンを使いたくなるのはよくある話だけど、エラーになる。

で、自分の場合、全部チェックしたけどエラーは消えなかった。

なんで?

自分がハマったところ

  • パラメータの順番が違う

ちなみに、自分が投げたクエリはこんな感じ。

CREATE EXTERNAL TABLE my_cloudtrail (
    eventVersion STRING,
    userIdentity STRUCT<
        type: STRING,
        principalId: STRING,
        arn: STRING,
        accountId: STRING,
        invokedBy: STRING,
        accessKeyId: STRING,
        userName: STRING,
        sessionContext: STRUCT<
            attributes: STRUCT<
                mfaAuthenticated: STRING,
                creationDate: STRING>,
            sessionIssuer: STRUCT<
                type: STRING,
                principalId: STRING,
                arn: STRING,
                accountId: STRING,
                userName: STRING>>>,
    eventTime STRING,
    eventSource STRING,
    eventName STRING,
    awsRegion STRING,
    sourceIpAddress STRING,
    userAgent STRING,
    errorCode STRING,
    errorMessage STRING,
    requestParameters STRING,
    responseElements STRING,
    additionalEventData STRING,
    requestId STRING,
    eventId STRING,
    resources ARRAY<STRUCT<
        arn: STRING,
        accountId: STRING,
        type: STRING>>,
    eventType STRING,
    apiVersion STRING,
    readOnly STRING,
    recipientAccountId STRING,
    serviceEventDetails STRING,
    sharedEventID STRING,
    vpcEndpointId STRING
)
PARTITIONED BY ( region STRING, year STRING )
COMMENT 'CloudTrail table for cloudtrail archive'
ROW FORMAT SERDE 'com.amazon.emr.hive.serde.CloudTrailSerde'
STORED AS INPUTFORMAT 'com.amazon.emr.cloudtrail.CloudTrailInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION 's3://my-bucket-name/AWSLogs/my-account-id/CloudTrail/'
TBLPROPERTIES ('classification'='cloudtrail');

よくあるCloudTrailのログを元にAthenaにテーブルを作成するクエリ。
でも、これはエラーになる。

なぜなら、COMMENTとPARTITIONED BYの行の順番が逆だから

つまり、DDLステートメント CREATE TABLE はパラメーターの順序もチェックするので、COMMENTとPARTITIONED BYの行を入れ替えて実行すると、テーブルの作成が成功します。

まとめ

今回は、ドキュメントの読み方が良くなかったと反省しました。

簡易チェックには、Format Queryを使いましょう。
SQLを整形したタイミングで間違っていると、パッと見でだいぶ違和感ある感じに整形されるので気づきやすいと思います。

誰かが同じ道を踏んだ時に、お役に立てば幸いです。