/home/by-natures/dev*

データ界隈で働くエンジニアとしての技術的なメモと、たまに普通の日記。

2019/01/22-23 AWS Glue Crawler が struct をカラムに持つテーブルに使いづらい

AWS Glue を色々と触っているのですが、どうにも正しい使い方がよく分からなくなってきました。

Glue Job で Parquet フォーマットで書き出して Athena から読み込みたいのですが、パーティションによってキー数が大きく異なる JSON 形式のカラムがあるためにうまくいきません。統一的に扱うなら string にして保存してしまえば良いんですけど、そうすると SparkSQL で上手く扱えない(SparkSQL で string を JSON として扱う方法があれば教えてください ありました、get_json_object 関数を使うことで string 形式の JSON からバリューを抜き出すことができました。)。

Glue Job で string ではなく struct で書き出すと、Glue Crawler がパーティションごとに異なるスキーマを生成してしまい、テーブル全体としてスキーマが一致しない(incompatible) ので Athena で読めない。その場合のエラーは HIVE_PARTITION_SCHEMA_MISMATCH なので、回避方法はあります:

https://forums.aws.amazon.com/thread.jspa?messageID=805011

Athena と AWS Glue を併用する際のベストプラクティス - Amazon Athena

stackoverflow.com

ただこれを回避すると、別の HIVE_CANNOT_OPEN_SPLIT というエラーが。私の環境では Schema mismatch, metastore schema for row column contents has 185 fields but parquet schema has 149 fields と出ます。色々 Glue Crawler 上で試しましたが回避方法は見つかっていません。

adtech-blog.united.jp

結局、struct を使うのが問題の根源なので、 string か、せめて map<string,string> のようなもう少し汎用的な形で保存できればよいなと思っています。これなら Crawler ではなく MSCK REPAIR TABLE コマンドでパーティション追加するだけでいけるはず。ただこれを Glue Job(PySpark) で実現する方法がまだ分かりません。

Glue は便利そうだなと思っていましたが、Crawler のようなデータ管理をよしなにやってくれるサービスが上手くいかないと逆に検証に時間を取られて徒労に終わってしまうなぁと思った今日この頃。。結局 Spark でのデータ変換をきちんと勉強して地道に変換した方が早い気がしています。

追記

上で記載しましたが、 get_json_object という関数を利用することで string 形式の JSON からバリューを抜き出すことができました。とりあえずこれで、 Glue Job で string 形式で保存した上で、あとから SparkSQL でアクセスすることができます。

API ドキュメントはこちら。先週結構探したつもりだったんですが、今日さがしたらすぐに見つかりました。。

spark.apache.org