Amazon EMR のバージョンアップ 2/3:メジャーバージョンアップで遭遇した問題

前回の続きです。

EMR 5.36.1 から EMR 6.6.0 への更新について書きます。

EMR 5.36.1 から EMR 6.6.0 への更新

アプリケーション等 EMR 5.36.1 EMR 6.6.0
Tez 0.9.2 0.9.2
Hue 4.10.0 4.10.0
Hive 2.3.9 3.1.2
Hadoop 2.10.1 3.2.1
Presto 0.267 0.267
Trino N/A 367
Amazon Linux 2 2

このバージョンアップでは Hive と Hadoop のメジャーバージョンアップがあるので、Upgrade Amazon EMR Hive Metastore from 5.X to 6.X | AWS Big Data Blog のとおりに Hive メタストアをマイグレートしました。

その後、検証用 EMR cluster を作成してクエリの互換性を検証したところいくつか問題が見つかりました。

Hive クエリの問題1

Repro ではいくつかのバッチで後続の処理を高速化するために Avro 形式で保存されているデータを Parquet 形式に変換しています。変換元テーブルに ARRAY 型のカラムがあり、その要素数が 500 を越える行がある場合 ArrayIndexOutOfBoundsException が発生していました。 このエラーは EMR のバージョンを 6.15.0 まで上げると発生しなくなりました。どのバージョンで直ったかまでは特定していませんが、検証では以下の結果でした。

  • NG: emr-6.6.0 (Hive 3.1.2)
  • NG: emr-6.10.0 (Hive 3.1.3)
  • OK: emr-6.15.0 (Hive 3.1.3)

リリースノートを確認したところ Amazon EMR 6.12.0 - Hive release notes - Amazon EMRArrayIndexOutOfBoundsException に関する修正が2件ありました。

Hive クエリの問題2

また Hive のメジャーバージョンアップがあったので、独自開発した Hive UDF の修正が必要でした。この UDF はあるテーブルを Parquet 形式に変換するときにあるカラムの型を以下のように変換するためのものです。

Befoer: ARRAY<STRUCT<custom_event_id: BIGINT, name: STRING, properties: STRING, tracked_at: STRING, idx: BIGINT>>
After:  ARRAY<STRUCT<custom_event_id: BIGINT, name: STRING, properties: MAP<STRING, STRING>, tracked_at: TIMESTAMP, idx: BIGINT>>

properties というフィールドには JSON 文字列が入っているので MAP<STRING, STRING> に変換します。

この独自開発した Hive UDF を使ったクエリが動作が怪しくなりました。

Vectorized Query Execution 1 は Repro の環境では有効だったのですが、これが有効のままだと独自開発した Hive UDF を使ったクエリの実行時に以下のエラーが発生しました。

Caused by: java.lang.RuntimeException: org.apache.hadoop.hive.ql.metadata.HiveException: Hive Runtime Error while processing vector batch (tag=0) (vectorizedVertexNum 1)

そこで Vectorized Query Execution を無効にして試したところ、独自開発した Hive UDF の部分で型のエラーが発生しました。この Hive UDF の型エラーを修正するとクエリは通ったのですが、実行時間が大幅に長くなってしまいました。この実行時間の増加は受け入れられるものではありませんでした。

この挙動は EMR 6.15.0 でも変わりませんでした。また Vectorized Query Execution の有効・無効によって UDF に渡ってくるオブジェクトの型が変わってしまう挙動についても同様でした。2

幸いなことに独自開発した Hive UDF を使ったクエリは他の集計方法で代替可能なものだったため、このクエリを廃止してバッチのフローを変更することにしました。 このクエリで更新しているテーブルは、別のチームが将来的に廃止する予定でしたが、予定を早めて廃止することにしました。

元のバッチでは以下のように動作していました。

  1. Hive で S3 にあるデータを Parquet 形式に変換して S3 に書き込み
  2. Presto で↑で作成したデータを集計して結果を S3 に Parquet 形式で書き込み

それを以下のように変更することにしました。

  1. Presto(Trino) で BigQuery にあるデータを集計して結果を S3 に Parquet 形式で書き込み

この BigQuery にあるテーブルには今回の集計に関連しないカラムで JSON 型が使われていました。そのため JSON 型に対応していない Presto の BigQuery connector を使ってこのテーブルを参照できませんでした。3

EMR 6.15.0 では Trino 426 を利用可能です。Trino の BigQuery connector は JSON 型をサポートしています4

以上から Rerpo のユースケースでは EMR 5.36.1 から EMR 6.6.0 への更新はできず、 EMR 5.36.1 から EMR 6.15.0 への更新と Presto から Trino への移行を同時にやる必要があることがわかりました。

次回予告

EMR 5.36.1 から EMR 6.6.0 への更新ができないことがわかりました。次回は EMR 6.15.0 への更新について書いていきます。


  1. https://cwiki.apache.org/confluence/display/hive/vectorized+query+execution
  2. このあたりの調査には AWS のサポートにも協力していただきました。
  3. Presto の BigQuery connector は BigQuery の JSON 型をサポートしていません。BigQuery Connector — Presto 0.286 Documentation
  4. BigQuery connector — Trino 444 Documentation