LoginSignup
5
2

More than 3 years have passed since last update.

【AWS Athena】エラー HIVE_BAD_DATA: Field label's type {A} in parquet is incompatible with type {B} defined in table schema でハマった話

Last updated at Posted at 2020-04-19

私がAWS AthenaおよびAWS Glueでメタデータの取り扱いでハマった話を共有いたします。

ハマった経緯

  1. parquetのデータをS3に配置する
  2. Glueのテーブルを作成する
  3. AthenaでSELECT文を実行するため、load partition()を実行しパーティションを読み込む
  4. AthenaでSELECT文を実行する → parquet内でのデータ型の定義とGlueテーブルのテーブル定義に齟齬があるためエラーと表示される
  5. テーブル定義を誤っていたことに気づきGlueのテーブル情報を修正する
  6. AthenaでSELECT文を実行する → なぜかparquet内でのデータ型の定義とGlueテーブルのテーブル定義に齟齬があるためエラーと表示される(困惑)

ハマった状況を再現

そのとき、ハマった状況を再現していきます。
まず、S3に配置するparquetをpysparkを使って作成する。

from pyspark.sql.types import StructType
from pyspark.sql.types import StructField
from pyspark.sql.types import StringType
from pyspark.sql.types import IntegerType
rdd = sc.parallelize([
    ('apple', 120),
    ('banana', 220),
    ('tomato', 320),
    ('chicken', 300),
    ])
schema = StructType([
    StructField('label', StringType(), False),
    StructField('value', IntegerType(), False),
    ])
df = spark.createDataFrame(rdd, schema)
df.repartition(1).write.parquet('./output/')

dfの中身はこのようになっております。
labelのカラムがstring型、valueのカラムがint型です。
スキーマ情報20200419.png

これをS3に配置します。今回は s3://inu-is-dog/2020-04-19-qiita/id=123/part-00000.snappy.parquet へ配置いたしました。
id=123がパーティションとなるのがミソです。

s3path20200419.png

次にGlueでテーブルを手動で作成いたします。

  • データベース名:sampledb
  • テーブル名:table_20200419
  • データストア:s3://inu-is-dog/2020-04-19-qiita/
  • データ形式:Parquet
  • スキーマ:
    • id(パーティションキー) [string]
    • label [int]
    • value [int]

あえて、スキーマのlabelのデータ型はstring型ではなく、int型(誤り)としています。
テーブル.png

次にAthenaの画面に遷移します。
今回はidのパーティションを持つテーブルを作成したため、SELECT文を実行する前にid=123のパーティションを登録する。

ALTER TABLE sampledb.table_20200419 ADD PARTITION (id = '123');

クエリ.png

それでは、SELECT文を実行してみましょう。

SELECT * 
FROM sampledb.table_20200419;

エラー.png

"HIVE_BAD_DATA: Field label's type BINARY in parquet is incompatible with type int defined in table schema"とエラーが表示されました。

Glueのテーブル登録でlabelのデータ型を誤って登録していたことが原因でしょう。

...ということで、table_20200419のスキーマの編集を行いました。

テーブル2.png

これで先ほどのSELECT文は通るはず....

aa.png

ダメでした.... 同じエラーメッセージです。(困惑)

Athenaの画面の左側のテーブル情報を見てもわかるのですがlabelのカラムは正常にstring型に更新されております。
それなら、なぜまた同じエラーメッセージなのか??

原因

Glueのテーブル table_20200419へ画面を遷移させ、[パーティションの表示] → [id=123のプロパティの表示]をさせてみましょう。
プロパティ1.png
プロパティ2.png

id=123のパーティションではlabelはint型で扱うように設定されていることがわかります。

パーティションごとのメタデータはそのパーティションを読み込んだ際のテーブル情報が登録されており、大元のテーブルの変更は反映されていないということになります。

対処法

この原因を踏まえて、大元のテーブルのカラム情報が変更された際には今まで読み込んでいたパーティションのメタデータも更新する必要があることがわかりました。

パーティションをDROPした後、改めてパーティションを読み込む対応方法を共有いたします。

ALTER TABLE sampledb.table_20200419 DROP PARTITION (id = '123');
ALTER TABLE sampledb.table_20200419 ADD PARTITION (id = '123');

これで無事、SELECT文が通るようになりました。
サクセス.png

この記事がみなさまの開発や分析の一助となれば幸いです。

5
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2