

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# Hudi
<a name="emr-hudi"></a>

[Apache Hudi](https://hudi.apache.org/) は、増分データの処理とデータパイプラインの開発をシンプルにするオープンソースのデータ管理フレームワークであり、レコードレベルの挿入、更新、アップサート、および削除機能を備えています。*アップサート*とは、既存のデータセットにレコードがまだ存在しない場合は挿入し、存在する場合は更新する機能を指します。Amazon S3 でのデータのレイアウト方法を効率的に管理することで、Hudi はデータをほぼリアルタイムで取り込んで更新できます。Hudi は、データセットに対して実行されたアクションのメタデータをきめ細かく管理して、アクションをアトミックで整合性のある状態にするのに役立ちます。

Hudi は、[Apache Spark](https://aws.amazon.com/emr/features/spark/)、[Apache Hive](https://hive.apache.org/)、および [Presto](https://prestodb.github.io) と統合されています。Amazon EMR リリースバージョン 6.1.0 以降では、Hudi は [Trino (PrestoSQL)](https://trino.io/) とも統合されています。

Amazon EMR リリースバージョン 5.28.0 以降では、EMR は Spark、Hive、Presto、または Flink のインストール時に、デフォルトで Hudi コンポーネントをインストールします。Spark または Hudi DeltaStreamer ユーティリティを使用して、Hudi データセットを作成したり更新したりできます。Hive、Spark、Presto、または Flink を使用して、Hudi データセットをインタラクティブにクエリしたり、増分プルを使用してデータ処理パイプラインを構築したりできます。増分プルとは、2 つのアクション間で変更されたデータのみをプルする機能を指します。

これらの機能により、Hudi は以下のユースケースに適しています。
+ 特定のデータの挿入および更新イベントを必要とするセンサーやその他のモノのインターネット (IoT) デバイスからのストリーミングデータを操作する。
+ ユーザーがデータの使用方法について忘れたり、同意を変更したりする可能性のあるアプリケーションのデータプライバシー規制を遵守する。
+ 経時的に変更をデータセットに適用できる[変更データキャプチャ (CDC) システム](https://en.wikipedia.org/wiki/Change_data_capture)を実装する。

次の表は、Amazon EMR 7.x シリーズの最新リリースに含まれている Hudi のバージョンと、Amazon EMR で Hudi と共にインストールされるコンポーネントを示しています。

このリリースで Hudi と共にインストールされるコンポーネントのバージョンについては、[「リリース 7.12.0 コンポーネントバージョン](emr-7120-release.md)」を参照してください。


**emr-7.12.0 の Hudi バージョン情報**  

| Amazon EMR リリースラベル | Hudi バージョン | Hudi でインストールされるコンポーネント | 
| --- | --- | --- | 
| emr-7.12.0 | Hudi 1.0.2-amzn-1 | Not available. | 

次の表は、Amazon EMR 6.x シリーズの最新リリースに含まれている Hudi のバージョンと、Amazon EMR で Hudi と共にインストールされるコンポーネントを示しています。

このリリースで Hudi と共にインストールされるコンポーネントのバージョンについては、「[リリース 6.15.0 コンポーネントバージョン](emr-6150-release.md)」を参照してください。


**emr-6.15.0 の Hudi バージョン情報**  

| Amazon EMR リリースラベル | Hudi バージョン | Hudi でインストールされるコンポーネント | 
| --- | --- | --- | 
| emr-6.15.0 | Hudi 0.14.0-amzn-0 | Not available. | 

**注記**  
Amazon EMR リリース 6.8.0 には [Apache Hudi](https://hudi.apache.org/) 0.11.1 が付属していますが、Amazon EMR 6.8.0 クラスターは Hudi 0.12.0 のオープンソース `hudi-spark3.3-bundle_2.12` とも互換性があります。

次の表は、Amazon EMR 5.x シリーズの最新リリースに含まれている Hudi のバージョンと、Amazon EMR で Hudi と共にインストールされるコンポーネントを示しています。

このリリースで Hudi と共にインストールされるコンポーネントのバージョンについては、「[Release 5.36.2 Component Versions](emr-5362-release.md)」を参照してください。


**emr-5.36.2 の Hudi バージョン情報**  

| Amazon EMR リリースラベル | Hudi バージョン | Hudi でインストールされるコンポーネント | 
| --- | --- | --- | 
| emr-5.36.2 | Hudi 0.10.1-amzn-1 | Not available. | 

**Topics**
+ [Hudi の仕組み](emr-hudi-how-it-works.md)
+ [Amazon EMR で Hudi を使用する際の考慮事項と制限事項](emr-hudi-considerations.md)
+ [Hudi がインストールされたクラスターを作成する](emr-hudi-installation-and-configuration.md)
+ [Hudi データセットを操作する](emr-hudi-work-with-dataset.md)
+ [Hudi CLI を使用する](emr-hudi-cli.md)
+ [Hudi リリース履歴](Hudi-release-history.md)

# Hudi の仕組み
<a name="emr-hudi-how-it-works"></a>

Amazon EMR で Hudi を使用する場合、Spark Data Source API または Hudi DeltaStreamer ユーティリティを使用して、データセットにデータを書き込むことができます。Hudi は、`basepath` の下で、従来の Hive テーブルに似たパーティション分割されたディレクトリ構造にデータセットを編成します。これらのディレクトリ内のファイルとしてのデータのレイアウト方法の詳細は、選択したデータセットタイプによって異なります。書き込み時コピー (CoW) または読み取り時マージ (MoR) を選択できます。

データセットタイプにかかわらず、データセット内の各パーティションは `basepath` に対する `partitionpath` によって一意に識別されます。各パーティション内で、レコードは複数のデータファイルに分散されます。詳細については、Apache Hudi ドキュメントの「[File management](https://hudi.apache.org/docs/concepts.html#file-management)」を参照してください。

Hudi の各アクションには、対応するコミットがあり、*インスタント*と呼ばれる単調に増加するタイムスタンプで識別されます。Hudi は、データセットに対して実行された一連のすべてのアクションをタイムラインとして保持します。Hudi は、タイムラインを使用して、読み取り側と書き込み側のスナップショット分離を提供し、前の時点にロールバックできるようにします。Hudi が記録するアクションとアクションの状態の詳細については、Apache Hudi ドキュメントの「[タイムライン](https://hudi.apache.org/docs/concepts.html#timeline)」を参照してください。

## データセットストレージタイプについて: 書き込み時にコピーおよび読み取り時にマージ
<a name="emr-hudi-data-files"></a>

Hudi データセットを作成するときに、データセットが書き込み時コピーであるか読み取り時マージであるかを指定します。
+ **書き込み時コピー (CoW)** – データは列形式 (Parquet) で保存され、更新ごとに書き込み中にファイルの新しいバージョンが作成されます。CoW はデフォルトのストレージタイプです。
+ **読み取り時マージ (MoR)** – データは、列形式 (Parquet) 形式と行形式 (Avro) の組み合わせを使用して保存されます。更新は、行形式の*差分*ファイルに記録され、必要に応じて圧縮されて、新しいバージョンの列形式のファイルが作成されます。

CoW データセットでは、レコードが更新されるたびに、そのレコードを含むファイルが更新された値で書き換えられます。MoR データセットでは、更新があるたびに、Hudi によって変更されたレコードの行のみが書き込まれます。MoR は、読み取りが少なく書き込みまたは変更が多いワークロードに適しています。CoW は、頻繁に変更されないデータの読み取りが多いワークロードに適しています。

Hudi は、データにアクセスするための 3 つの論理ビューを提供します。
+ **読み取り最適化ビュー** – CoW テーブルからの最新のコミットされたデータセットと、MoR テーブルからの最新の圧縮されたデータセットを提供します。
+ **増分ビュー** – CoW データセットからの 2 つのアクション間の変更ストリームを、ダウンストリームジョブと ETL (抽出、変換、ロード) ワークフローのフィード用に提供します。
+ **リアルタイムビュー** – 列形式のファイルと行形式のファイルをインラインでマージすることで、MoR テーブルからの最新のコミットされたデータを提供します。

読み取り最適化ビューをクエリすると、クエリからすべての圧縮されたデータが返されますが、このデータには最新の差分コミットは含まれていません。このデータをクエリすると、読み取りパフォーマンスは向上しますが、最新のデータは省かれています。リアルタイムビューをクエリすると、圧縮されたデータが Hudi によって読み取り時に差分コミットにマージされます。最新のデータがクエリに使用可能になりますが、マージのコンピューティングオーバーヘッドにより、クエリのパフォーマンスが低下します。圧縮されたデータまたはリアルタイムデータのいずれかをクエリする機能では、クエリ時にパフォーマンスと柔軟性のどちらを優先させるかを選択できます。

ストレージタイプ間での優先項目の選択の詳細については、Apache Hudi ドキュメントの「[Storage Types & Views](https://hudi.apache.org/docs/concepts.html#storage-types--views)」を参照してください。

Hudi は MoR のために、Hive Metastore に 2 つのテーブルを作成します。ひとつは読み込み最適化ビューで使用するための、ユーザーが指定したテーブルです。もうひとつはリアルタイムビューで使用するための、同名テーブルの末尾に `_rt` が付与されたテーブルです。両方のテーブルをクエリできます。

## メタストアへの Hudi データセットの登録
<a name="emr-hudi-hive-metastore"></a>

Hudi テーブルを Hive メタストアに登録すると、他のテーブルと同様に、Hive、Spark SQL、または Presto を使用して Hudi テーブルをクエリできます。さらに、 Glue データカタログ AWS をメタストアとして使用するように Hive と Spark を設定することで、Hudi を AWS Glue と統合できます。MoR テーブルの場合、Hudi はデータセットをメタストアの 2 つのテーブルとして登録します。それらは、指定した名前のテーブル (読み取り最適化ビュー) と、同じ名前で `_rt` を付加したテーブル (リアルタイムビュー) です。

Spark を使用して Hudi データセットを作成するときに、Hudi テーブルを Hive メタストアに登録します。そのためには、`HIVE_SYNC_ENABLED_OPT_KEY` オプションを `"true"` に設定し、他の必要なプロパティを指定します。詳細については、「[Hudi データセットを操作する](emr-hudi-work-with-dataset.md)」を参照してください。さらに、hive\$1sync\$1tool コマンドラインユーティリティを使用して、Hudi データセットを個別にテーブルとしてメタストアに登録できます。

# Amazon EMR で Hudi を使用する際の考慮事項と制限事項
<a name="emr-hudi-considerations"></a>
+ **レコードキーフィールドを null または空にすることはできない** - レコードキーフィールドとして指定するフィールドには、`null` または空の値を指定できません。
+ **upsert および insert でスキーマがデフォルトで更新される** — Hudi にはインターフェイス `HoodieRecordPayload` が備わっており、これにより、入力 DataFrame と既存の Hudi データセットをマージして、新しい更新されたデータセットを生成する方法が決定されます。Hudi には、このクラスのデフォルト実装 `OverwriteWithLatestAvroPayload` があります。これにより、入力 DataFrame で指定されているように既存のレコードが上書きされ、スキーマが更新されます。マージおよび部分的な更新を実装するためにこのロジックをカスタマイズするには、`DataSourceWriteOptions.PAYLOAD_CLASS_OPT_KEY` パラメータを使用して `HoodieRecordPayload` インターフェイスの実装を提供できます。
+ **削除にはスキーマが必要** - 削除するときは、レコードキー、パーティションキー、事前結合キーのフィールドを指定する必要があります。他の列は `null` または空にすることができますが、完全なスキーマが必要です。
+ **MoR テーブルの制限** — MOR テーブルではセーブポイントはサポートされていません。Spark SQL、Presto、または Hive から、読み取り最適化ビューまたはリアルタイムビュー (`tableName_rt`) を使用して MoR テーブルをクエリできます。読み取り最適化ビューを使用した場合、ベースファイルデータのみが公開され、ベースデータとログデータのマージされたビューは公開されません。
+ **[Hive]**
  + テーブルを Hive メタストアに登録する場合、Hudi では、Hive Thrift サーバーがデフォルトのポート `10000` で実行されていると想定されます。このポートをカスタムポートで上書きする場合は、以下の例に示すように `HIVE_URL_OPT_KEY` オプションを渡します。

    ```
    .option(DataSourceWriteOptions.HIVE_URL_OPT_KEY, "jdbc:hive2://localhost:override-port-number
    ```
  + Spark の `timestamp` データ型は、Hive の `timestamp` 型としてではなく、Hive の `long` データ型として登録されます。
+ **Presto**
  + Presto では、Hudi バージョン 0.6.0 未満の場合、MoR リアルタイムテーブルの読み取りはサポートされていません。
  + Presto は、スナップショットクエリのみをサポートしています。
  + Presto で Hudi データセット列が正しく解釈されるためには、`hive.parquet_use_column_names` 値を `true` に設定します。
    + セッションの値を設定するには、Presto シェルで以下のコマンドを実行します。

      ```
      set session hive.parquet_use_column_names=true
      ```
    + クラスターレベルで値を設定するには、以下の例に示すように、`presto-connector-hive` 設定分類を使用して `hive.parquet.use_column_names` を `true` に設定します。詳細については、「[アプリケーションの設定](emr-configure-apps.md)」を参照してください。

      ```
      [
        {
          "Classification": "presto-connector-hive",
          "Properties": {
            "hive.parquet.use-column-names": "true"
          }
        }
      ]
      ```
+ **HBase インデックス**
  + Hudi の*構築*に使用した HBase のバージョンが、EMR リリースガイドに記載されているバージョンと異なる場合があります。Spark セッションに対して正しい依存関係をプルインするには、次のコマンドを実行します。

    ```
    spark-shell \
    --jars /usr/lib/spark/external/lib/spark-avro.jar,/usr/lib/hudi/cli/lib/*.jar \
    --conf "spark.serializer=org.apache.spark.serializer.KryoSerializer" \
    --conf "spark.sql.hive.convertMetastoreParquet=false"
    ```
+ **最高のパフォーマンスのための設定** – EMR 7.3 以降/Hudi 0.15 以降の場合、Kryo シリアル化のオーバーヘッドを減らすためにこの設定を設定することをお勧めします。

  ```
  --conf 'spark.kryo.registrator=org.apache.spark.HoodieKryoRegistrar'
  ```
**注記**  
EMR Serverless できめ細かなアクセスコントロール (FGAC) を使用している場合、ユーザーは KryoSerializer ではなく JavaSerializer を使用する必要があるので、この設定は不要です。

# Hudi がインストールされたクラスターを作成する
<a name="emr-hudi-installation-and-configuration"></a>

Amazon EMR リリースバージョン 5.28.0 以降では、Amazon EMR は Spark、Hive、または Presto のインストール時に、デフォルトで Hudi コンポーネントをインストールします。Amazon EMR で Hudi を使用するには、1 つまたは複数の以下のアプリケーションがインストールされたクラスターを作成します。
+ Hadoop
+ [Hive]
+ Spark
+ Presto
+ Flink

クラスターは、 AWS マネジメントコンソール、、 AWS CLIまたは Amazon EMR API を使用して作成できます。

## を使用して Hudi でクラスターを作成するには AWS マネジメントコンソール
<a name="emr-hudi-create-cluster-console"></a>

1. 新しい Amazon EMR コンソールに移動し、サイドナビゲーションから **[古いコンソールに切り替え]** を選択します。古いコンソールに切り替えたときの動作の詳細については、「[Using the old console](https://docs.aws.amazon.com/emr/latest/ManagementGuide/whats-new-in-console.html#console-opt-in)」を参照してください。

1. [**Create cluster (クラスターの作成)**]、[**Go to advanced options (詳細オプションに移動する)**] の順に選択します。

1. [ソフトウェア設定] の **[リリース]** で **emr-5.28.0** 以降を選択し、**[Hadoop]**、**[Hive]**、**[Spark]**、**[Presto]**、**[Tez]** と、クラスターに必要なその他のアプリケーションを選択します。

1. アプリケーションに必要な他のオプションを設定し、[**Next (次へ)**] を選択します。

1. 必要に応じて、[**ハードウェア**] と [**General cluster settings (全般クラスター設定)**] のオプションを設定します。

1. [**Security Options (セキュリティオプション)**] で、マスターノードのコマンドラインへの SSH による接続に使用できる [**EC2 キーペア**] を選択することをお勧めします。これにより、このガイドで説明されている Spark シェルコマンド、Hive CLI コマンド、Hudi CLI コマンドを実行できます。

1. 必要に応じて他のセキュリティオプションを選択し、[**クラスターの作成**] を選択します。

# Hudi データセットを操作する
<a name="emr-hudi-work-with-dataset"></a>

Hudi は、Spark を介した Hudi データセットのデータの挿入、更新、削除をサポートしています。詳細については、Apache Hudi ドキュメントの「[Writing Hudi Tables](https://hudi.apache.org/docs/writing_data.html)」を参照してください。

以下の例では、インタラクティブな Spark シェルを起動し、Spark submit を使用するか、Amazon EMR Notebooks を使用して、Amazon EMR で Hudi を操作する方法を示しています。Hudi DeltaStreamer ユーティリティまたは他のツールを使用して、データセットに書き込むこともできます。このセクション全体を通して、例では、デフォルトの `hadoop` ユーザーとして、SSH を使用してマスターノードに接続しながら、Spark シェルを使用してデータセットを操作する方法を示しています。

## Amazon EMR 6.7 以降を使用して Spark シェルを起動する
<a name="hudi-datasets-67"></a>

Amazon EMR 6.7.0 以降を使用して、`spark-shell`、`spark-submit`、または `spark-sql` を実行している場合は、次のコマンドを渡します。

**注記**  
Amazon EMR 6.7.0 は [Apache Hudi](https://hudi.apache.org/) 0.11.0-amzn-0 を使用していますが、これは以前の Hudi バージョンよりも大幅に改善されています。詳細については、「[Apache Hudi 0.11.0 Migration Guide](https://hudi.apache.org/releases/release-0.11.0/#migration-guide)」を参照してください。このタブの例にはこれらの変更が反映されています。

**プライマリノードで Spark シェルを開くには**

1. SSH を使用してプライマリノードに接続します。詳細については、「*Amazon EMR 管理ガイド*」の「[Connect to the primary node using SSH](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-connect-master-node-ssh.html)」を参照してください。

1. 以下のコマンドを入力して、Spark シェルを起動します。PySpark shell を使用するには、*spark-shell* を *pyspark* に置き換えてください。

   ```
   spark-shell --jars /usr/lib/hudi/hudi-spark-bundle.jar \
   --conf "spark.serializer=org.apache.spark.serializer.KryoSerializer" \    
   --conf "spark.sql.catalog.spark_catalog=org.apache.spark.sql.hudi.catalog.HoodieCatalog"  \
   --conf "spark.sql.extensions=org.apache.spark.sql.hudi.HoodieSparkSessionExtension"
   ```

## Amazon EMR 6.6 以前を使用して Spark シェルを起動する
<a name="hudi-datasets-67"></a>

Amazon EMR 6.6.x 以前を使用して、`spark-shell`、`spark-submit`、または `spark-sql` を実行している場合は、次のコマンドを渡します。

**注記**  
Amazon EMR 6.2 および 5.31 以降 (Hudi 0.6.x 以降) では、`spark-avro.jar` を設定から省略できます。
Amazon EMR 6.5 および 5.35 以降 (Hudi 0.9.x 以降) では、`spark.sql.hive.convertMetastoreParquet=false` を設定から省略できます。
Amazon EMR 6.6 および 5.36 以降 (Hudi 0.10.x 以降) には、「[Version: 0.10.0 Spark Guide](https://hudi.apache.org/docs/0.10.0/quick-start-guide/)」に記載されている `HoodieSparkSessionExtension` 設定が含まれている必要があります。  

  ```
  --conf  "spark.sql.extensions=org.apache.spark.sql.hudi.HoodieSparkSessionExtension" \
  ```

**プライマリノードで Spark シェルを開くには**

1. SSH を使用してプライマリノードに接続します。詳細については、「*Amazon EMR 管理ガイド*」の「[Connect to the primary node using SSH](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-connect-master-node-ssh.html)」を参照してください。

1. 以下のコマンドを入力して、Spark シェルを起動します。PySpark shell を使用するには、*spark-shell* を *pyspark* に置き換えてください。

   ```
   spark-shell \
   --conf "spark.serializer=org.apache.spark.serializer.KryoSerializer" \
   --conf "spark.sql.hive.convertMetastoreParquet=false" \
   --jars /usr/lib/hudi/hudi-spark-bundle.jar,/usr/lib/spark/external/lib/spark-avro.jar
   ```

## Amazon EMR 6.7 以降を使用する Amazon EMR Notebooks で Hudi を使用する
<a name="hudi-datasets-notebooks"></a>

Amazon EMR Notebooks で Hudi を使用するには、まずローカルファイルシステムから Hudi jar ファイルをノートブッククラスターのマスターノードの HDFS にコピーする必要があります。次に、ノートブックエディタで、Hudi を使用するように EMR notebook を設定します。

**Amazon EMR Notebooks で Hudi を使用するには**

1. Amazon EMR Notebooks 用のクラスターを作成して起動します。詳細については、「*Amazon EMR 管理ガイド*」の「[ノートブックの Amazon EMR クラスターの作成](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-managed-notebooks-cluster.html)」を参照してください。

1. SSH を使用してクラスターのマスターノードに接続し、以下の例に示すようにローカルファイルシステムから HDFS に jar ファイルをコピーします。この例では、ファイルの管理をわかりやすくするために、HDFS にディレクトリを作成しています。必要に応じて、HDFS で独自のターゲットを選択できます。

   ```
   hdfs dfs -mkdir -p /apps/hudi/lib
   ```

   ```
   hdfs dfs -copyFromLocal /usr/lib/hudi/hudi-spark-bundle.jar /apps/hudi/lib/hudi-spark-bundle.jar
   ```

1. ノートブックエディタを開き、以下の例のコードを入力して実行します。

   ```
   %%configure
   { "conf": {
               "spark.jars":"hdfs:///apps/hudi/lib/hudi-spark-bundle.jar",
               "spark.serializer":"org.apache.spark.serializer.KryoSerializer",
               "spark.sql.catalog.spark_catalog": "org.apache.spark.sql.hudi.catalog.HoodieCatalog",
               "spark.sql.extensions":"org.apache.spark.sql.hudi.HoodieSparkSessionExtension"
             }}
   ```

## Amazon EMR 6.6 以前を使用する Amazon EMR Notebooks で Hudi を使用する
<a name="hudi-datasets-notebooks-66"></a>

Amazon EMR Notebooks で Hudi を使用するには、まずローカルファイルシステムから Hudi jar ファイルをノートブッククラスターのマスターノードの HDFS にコピーする必要があります。次に、ノートブックエディタで、Hudi を使用するように EMR notebook を設定します。

**Amazon EMR Notebooks で Hudi を使用するには**

1. Amazon EMR Notebooks 用のクラスターを作成して起動します。詳細については、「*Amazon EMR 管理ガイド*」の「[ノートブックの Amazon EMR クラスターの作成](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-managed-notebooks-cluster.html)」を参照してください。

1. SSH を使用してクラスターのマスターノードに接続し、以下の例に示すようにローカルファイルシステムから HDFS に jar ファイルをコピーします。この例では、ファイルの管理をわかりやすくするために、HDFS にディレクトリを作成しています。必要に応じて、HDFS で独自のターゲットを選択できます。

   ```
   hdfs dfs -mkdir -p /apps/hudi/lib
   ```

   ```
   hdfs dfs -copyFromLocal /usr/lib/hudi/hudi-spark-bundle.jar /apps/hudi/lib/hudi-spark-bundle.jar
   ```

   ```
   hdfs dfs -copyFromLocal /usr/lib/spark/external/lib/spark-avro.jar /apps/hudi/lib/spark-avro.jar
   ```

1. ノートブックエディタを開き、以下の例のコードを入力して実行します。

   ```
   { "conf": {
               "spark.jars":"hdfs:///apps/hudi/lib/hudi-spark-bundle.jar,hdfs:///apps/hudi/lib/spark-avro.jar",
               "spark.serializer":"org.apache.spark.serializer.KryoSerializer",
               "spark.sql.hive.convertMetastoreParquet":"false"
             }}
   ```

## Hudi の Spark セッションを初期化する
<a name="emr-hudi-initialize-session"></a>

Scala を使用する場合、Spark セッションで次のクラスをインポートする必要があります。この操作は、Spark セッションごとに 1 回行う必要があります。

```
import org.apache.spark.sql.SaveMode
import org.apache.spark.sql.functions._
import org.apache.hudi.DataSourceWriteOptions
import org.apache.hudi.DataSourceReadOptions
import org.apache.hudi.config.HoodieWriteConfig
import org.apache.hudi.hive.MultiPartKeysValueExtractor
import org.apache.hudi.hive.HiveSyncConfig
import org.apache.hudi.sync.common.HoodieSyncConfig
```

## Hudi データセットに書き込む
<a name="emr-hudi-dataframe"></a>

以下の例では、DataFrame を作成し、それを Hudi データセットとして書き込む方法を示しています。

**注記**  
コードサンプルを Spark シェルに貼り付けるには、プロンプトで「**:paste**」と入力し、例を貼り付けて、**CTRL** \$1 **D** を押します。

DataFrame を Hudi データセットに書き込むたびに、`DataSourceWriteOptions` を指定する必要があります。これらのオプションの多くは、書き込みオペレーション間で共通することがよくあります。この例では、`hudiOptions` 変数を使用して、後続の例でも使用する共通のオプションを指定しています。

### Amazon EMR 6.7 以降で Scala を使用する場合の書き込み
<a name="scala-examples-67"></a>

**注記**  
Amazon EMR 6.7.0 は [Apache Hudi](https://hudi.apache.org/) 0.11.0-amzn-0 を使用していますが、これは以前の Hudi バージョンよりも大幅に改善されています。詳細については、「[Apache Hudi 0.11.0 Migration Guide](https://hudi.apache.org/releases/release-0.11.0/#migration-guide)」を参照してください。このタブの例にはこれらの変更が反映されています。

```
// Create a DataFrame
val inputDF = Seq(
 ("100", "2015-01-01", "2015-01-01T13:51:39.340396Z"),
 ("101", "2015-01-01", "2015-01-01T12:14:58.597216Z"),
 ("102", "2015-01-01", "2015-01-01T13:51:40.417052Z"),
 ("103", "2015-01-01", "2015-01-01T13:51:40.519832Z"),
 ("104", "2015-01-02", "2015-01-01T12:15:00.512679Z"),
 ("105", "2015-01-02", "2015-01-01T13:51:42.248818Z")
 ).toDF("id", "creation_date", "last_update_time")

//Specify common DataSourceWriteOptions in the single hudiOptions variable 
val hudiOptions = Map[String,String](
  HoodieWriteConfig.TBL_NAME.key -> "tableName",
  DataSourceWriteOptions.TABLE_TYPE.key -> "COPY_ON_WRITE", 
  DataSourceWriteOptions.RECORDKEY_FIELD_OPT_KEY -> "id",
  DataSourceWriteOptions.PARTITIONPATH_FIELD_OPT_KEY -> "creation_date",
  DataSourceWriteOptions.PRECOMBINE_FIELD_OPT_KEY -> "last_update_time",
  DataSourceWriteOptions.HIVE_SYNC_ENABLED_OPT_KEY -> "true",
  DataSourceWriteOptions.HIVE_TABLE_OPT_KEY -> "tableName",
  DataSourceWriteOptions.HIVE_PARTITION_FIELDS_OPT_KEY -> "creation_date",
  HoodieSyncConfig.META_SYNC_PARTITION_EXTRACTOR_CLASS.key -> "org.apache.hudi.hive.MultiPartKeysValueExtractor",
  HoodieSyncConfig.META_SYNC_ENABLED.key -> "true",
  HiveSyncConfig.HIVE_SYNC_MODE.key -> "hms",
  HoodieSyncConfig.META_SYNC_TABLE_NAME.key -> "tableName",
  HoodieSyncConfig.META_SYNC_PARTITION_FIELDS.key -> "creation_date"
)

// Write the DataFrame as a Hudi dataset
(inputDF.write
    .format("hudi")
    .options(hudiOptions)
    .option(DataSourceWriteOptions.OPERATION_OPT_KEY,"insert")
    .mode(SaveMode.Overwrite)
    .save("s3://amzn-s3-demo-bucket/myhudidataset/"))
```

### Amazon EMR 6.6 以前で Scala を使用する場合の書き込み
<a name="scala-examples-66"></a>

```
// Create a DataFrame
val inputDF = Seq(
 ("100", "2015-01-01", "2015-01-01T13:51:39.340396Z"),
 ("101", "2015-01-01", "2015-01-01T12:14:58.597216Z"),
 ("102", "2015-01-01", "2015-01-01T13:51:40.417052Z"),
 ("103", "2015-01-01", "2015-01-01T13:51:40.519832Z"),
 ("104", "2015-01-02", "2015-01-01T12:15:00.512679Z"),
 ("105", "2015-01-02", "2015-01-01T13:51:42.248818Z")
 ).toDF("id", "creation_date", "last_update_time")

//Specify common DataSourceWriteOptions in the single hudiOptions variable 
val hudiOptions = Map[String,String](
  HoodieWriteConfig.TABLE_NAME -> "tableName",
  DataSourceWriteOptions.TABLE_TYPE_OPT_KEY -> "COPY_ON_WRITE", 
  DataSourceWriteOptions.RECORDKEY_FIELD_OPT_KEY -> "id",
  DataSourceWriteOptions.PARTITIONPATH_FIELD_OPT_KEY -> "creation_date",
  DataSourceWriteOptions.PRECOMBINE_FIELD_OPT_KEY -> "last_update_time",
  DataSourceWriteOptions.HIVE_SYNC_ENABLED_OPT_KEY -> "true",
  DataSourceWriteOptions.HIVE_TABLE_OPT_KEY -> "tableName",
  DataSourceWriteOptions.HIVE_PARTITION_FIELDS_OPT_KEY -> "creation_date",
  DataSourceWriteOptions.HIVE_PARTITION_EXTRACTOR_CLASS_OPT_KEY -> classOf[MultiPartKeysValueExtractor].getName
)

// Write the DataFrame as a Hudi dataset
(inputDF.write
    .format("org.apache.hudi")
    .option(DataSourceWriteOptions.OPERATION_OPT_KEY, DataSourceWriteOptions.INSERT_OPERATION_OPT_VAL)
    .options(hudiOptions)
    .mode(SaveMode.Overwrite)
    .save("s3://amzn-s3-demo-bucket/myhudidataset/"))
```

### PySpark を使用する場合の書き込み
<a name="pyspark-examples"></a>

```
# Create a DataFrame
inputDF = spark.createDataFrame(
    [
        ("100", "2015-01-01", "2015-01-01T13:51:39.340396Z"),
        ("101", "2015-01-01", "2015-01-01T12:14:58.597216Z"),
        ("102", "2015-01-01", "2015-01-01T13:51:40.417052Z"),
        ("103", "2015-01-01", "2015-01-01T13:51:40.519832Z"),
        ("104", "2015-01-02", "2015-01-01T12:15:00.512679Z"),
        ("105", "2015-01-02", "2015-01-01T13:51:42.248818Z"),
    ],
    ["id", "creation_date", "last_update_time"]
)

# Specify common DataSourceWriteOptions in the single hudiOptions variable
hudiOptions = {
'hoodie.table.name': 'tableName',
'hoodie.datasource.write.recordkey.field': 'id',
'hoodie.datasource.write.partitionpath.field': 'creation_date',
'hoodie.datasource.write.precombine.field': 'last_update_time',
'hoodie.datasource.hive_sync.enable': 'true',
'hoodie.datasource.hive_sync.table': 'tableName',
'hoodie.datasource.hive_sync.partition_fields': 'creation_date',
'hoodie.datasource.hive_sync.partition_extractor_class': 'org.apache.hudi.hive.MultiPartKeysValueExtractor'
}

# Write a DataFrame as a Hudi dataset
inputDF.write \
.format('org.apache.hudi') \
.option('hoodie.datasource.write.operation', 'insert') \
.options(**hudiOptions) \
.mode('overwrite') \
.save('s3://amzn-s3-demo-bucket/myhudidataset/')
```

**注記**  
コードの例や通知には、Hudi ではなく「hoodie」と表示されている場合があります。Hudi コードベースは、古い「hoodie」の綴りが広く使用されています。


**Hudi の DataSourceWriteOptions リファレンス**  

| オプション | 説明 | 
| --- | --- | 
|  TABLE\$1NAME  |  データセットを登録するテーブルの名前。  | 
|  TABLE\$1TYPE\$1OPT\$1KEY  |  オプション。データセットが `"COPY_ON_WRITE"` として作成されるか、`"MERGE_ON_READ"` として作成されるかを指定します。デフォルトは `"COPY_ON_WRITE"` です。  | 
|  RECORDKEY\$1FIELD\$1OPT\$1KEY  |  値が `HoodieKey` の `recordKey` コンポーネントとして使用されるレコードキーフィールド。実際の値は、フィールド値に対して `.toString()` を呼び出すことで取得されます。ネストされたフィールドは、`a.b.c` など、ドット表記を使用して指定できます。  | 
|  PARTITIONPATH\$1FIELD\$1OPT\$1KEY  |  値が `HoodieKey` の `partitionPath` コンポーネントとして使用されるパーティションパスフィールド。実際の値は、フィールド値に対して `.toString()` を呼び出すことで取得されます。  | 
|  PRECOMBINE\$1FIELD\$1OPT\$1KEY  |  実際の書き込みの前に事前結合で使用されるフィールド。2 つのレコードのキー値が同じ場合、Hudi は、`Object.compareTo(..)` で決定された事前結合フィールドの値が最も大きいレコードを選択します。  | 

以下のオプションは、Hudi データセットテーブルをメタストアに登録するためにのみ必要です。Hudi データセットを Hive メタストアのテーブルとして登録しない場合、これらのオプションは必要ありません。


**Hive の DataSourceWriteOptions リファレンス**  

| オプション | 説明 | 
| --- | --- | 
|  HIVE\$1DATABASE\$1OPT\$1KEY  |  同期先の Hive データベース。デフォルトは `"default"` です。  | 
|  HIVE\$1PARTITION\$1EXTRACTOR\$1CLASS\$1OPT\$1KEY  |  パーティションフィールド値を Hive パーティション列に抽出するために使用されるクラス。  | 
|  HIVE\$1PARTITION\$1FIELDS\$1OPT\$1KEY  |  Hive パーティション列を決定するために使用するデータセット内のフィールド。  | 
|  HIVE\$1SYNC\$1ENABLED\$1OPT\$1KEY  |  `"true"` に設定すると、データセットを Apache Hive メタストアに登録します。デフォルトは `"false"` です。  | 
|  HIVE\$1TABLE\$1OPT\$1KEY  |  必須。同期先の Hive テーブルの名前。例えば、`"my_hudi_table_cow"`。  | 
|  HIVE\$1USER\$1OPT\$1KEY  |  オプション。同期時に使用する Hive ユーザー名。例えば、`"hadoop"`。  | 
|  HIVE\$1PASS\$1OPT\$1KEY  |  オプション。`HIVE_USER_OPT_KEY` で指定されたユーザーの Hive パスワード。  | 
|  HIVE\$1URL\$1OPT\$1KEY  |  Hive メタストアの URL。  | 

## データのアップサート
<a name="emr-hudi-upsert-to-datasets"></a>

以下の例では、DataFrame を書き込むことでデータをアップサートする方法を示しています。以前の挿入の例とは異なり、`OPERATION_OPT_KEY` 値は `UPSERT_OPERATION_OPT_VAL` に設定されています。また、`.mode(SaveMode.Append)` は、レコードを付加する必要があることを指示するために指定されています。

### Amazon EMR 6.7 以降で Scala を使用する Upsert
<a name="scala-upsert-67"></a>

**注記**  
Amazon EMR 6.7.0 は [Apache Hudi](https://hudi.apache.org/) 0.11.0-amzn-0 を使用していますが、これは以前の Hudi バージョンよりも大幅に改善されています。詳細については、「[Apache Hudi 0.11.0 Migration Guide](https://hudi.apache.org/releases/release-0.11.0/#migration-guide)」を参照してください。このタブの例にはこれらの変更が反映されています。

```
// Create a new DataFrame from the first row of inputDF with a different creation_date value
val updateDF = inputDF.limit(1).withColumn("creation_date", lit("new_value"))

(updateDF.write
    .format("hudi")
    .options(hudiOptions)
    .option(DataSourceWriteOptions.OPERATION_OPT_KEY, "upsert")
    .mode(SaveMode.Append)
    .save("s3://amzn-s3-demo-bucket/myhudidataset/"))
```

### Amazon EMR 6.6 以前で Scala を使用する Upsert
<a name="scala-upsert-66"></a>

```
// Create a new DataFrame from the first row of inputDF with a different creation_date value
val updateDF = inputDF.limit(1).withColumn("creation_date", lit("new_value"))

(updateDF.write
    .format("org.apache.hudi")
    .option(DataSourceWriteOptions.OPERATION_OPT_KEY, DataSourceWriteOptions.UPSERT_OPERATION_OPT_VAL)
    .options(hudiOptions)
    .mode(SaveMode.Append)
    .save("s3://amzn-s3-demo-bucket/myhudidataset/"))
```

### PySpark を使用する Upsert
<a name="pyspark-upsert"></a>

```
from pyspark.sql.functions import lit

# Create a new DataFrame from the first row of inputDF with a different creation_date value
updateDF = inputDF.limit(1).withColumn('creation_date', lit('new_value'))

updateDF.write \
    .format('org.apache.hudi') \
    .option('hoodie.datasource.write.operation', 'upsert') \
    .options(**hudiOptions) \
    .mode('append') \
    .save('s3://amzn-s3-demo-bucket/myhudidataset/')
```

## レコードを削除する
<a name="emr-hudi-delete-from-datasets"></a>

レコードをハード削除するには、空のペイロードをアップサートします。この場合、`PAYLOAD_CLASS_OPT_KEY` オプションで `EmptyHoodieRecordPayload` クラスを指定しています。この例では、upsert の例で使用したのと同じ DataFrame `updateDF` を使用して、同じレコードが指定されるようにしています。

### Amazon EMR 6.7 以降で Scala を使用する場合の削除
<a name="scala-delete-67"></a>

**注記**  
Amazon EMR 6.7.0 は [Apache Hudi](https://hudi.apache.org/) 0.11.0-amzn-0 を使用していますが、これは以前の Hudi バージョンよりも大幅に改善されています。詳細については、「[Apache Hudi 0.11.0 Migration Guide](https://hudi.apache.org/releases/release-0.11.0/#migration-guide)」を参照してください。このタブの例にはこれらの変更が反映されています。

```
(updateDF.write
    .format("hudi")
    .options(hudiOptions)
    .option(DataSourceWriteOptions.OPERATION_OPT_KEY, "delete")
    .mode(SaveMode.Append)
    .save("s3://amzn-s3-demo-bucket/myhudidataset/"))
```

### Amazon EMR 6.6 以前で Scala を使用する場合の削除
<a name="scala-delete-66"></a>

```
(updateDF.write
    .format("org.apache.hudi")
    .option(DataSourceWriteOptions.OPERATION_OPT_KEY, DataSourceWriteOptions.UPSERT_OPERATION_OPT_VAL)
    .option(DataSourceWriteOptions.PAYLOAD_CLASS_OPT_KEY, "org.apache.hudi.common.model.EmptyHoodieRecordPayload")
    .mode(SaveMode.Append)
    .save("s3://amzn-s3-demo-bucket/myhudidataset/"))
```

### PySpark を使用する場合の削除
<a name="pyspark-delete"></a>

```
updateDF.write \
    .format('org.apache.hudi') \
    .option('hoodie.datasource.write.operation', 'upsert') \
    .option('hoodie.datasource.write.payload.class', 'org.apache.hudi.common.model.EmptyHoodieRecordPayload') \
    .options(**hudiOptions) \
    .mode('append') \
    .save('s3://amzn-s3-demo-bucket/myhudidataset/')
```

`OPERATION_OPT_KEY ` を `DELETE_OPERATION_OPT_VAL` に設定して、送信するデータセット内のすべてのレコードを削除し、データをハード削除することもできます。ソフト削除の実行方法、および Hudi テーブルに保存されたデータの削除の詳細については、Apache Hudi ドキュメントの「[Deletes](https://hudi.apache.org/docs/writing_data.html#deletes)」(削除) を参照してください。

## Hudi データセットから読み込む
<a name="emr-hudi-read-dataset"></a>

現時点でのデータを取得するために、Hudi はデフォルトでスナップショットクエリを実行します。以下に、[Hudi データセットに書き込む](#emr-hudi-dataframe) で S3 に書き込まれたデータセットをクエリする例を示します。*s3://amzn-s3-demo-bucket/myhudidataset* をテーブルパスに置き換え、パーティションレベルごとにワイルドカードのアスタリスクを追加し、*さらにアスタリスクを 1 つ追加します*。この例では、パーティションレベルが 1 つあるため、2 つのワイルドカードシンボルを追加しました。

### Amazon EMR 6.7 以降で Scala を使用する場合の読み込み
<a name="scala-read-67"></a>

**注記**  
Amazon EMR 6.7.0 は [Apache Hudi](https://hudi.apache.org/) 0.11.0-amzn-0 を使用していますが、これは以前の Hudi バージョンよりも大幅に改善されています。詳細については、「[Apache Hudi 0.11.0 Migration Guide](https://hudi.apache.org/releases/release-0.11.0/#migration-guide)」を参照してください。このタブの例にはこれらの変更が反映されています。

```
val snapshotQueryDF = spark.read
    .format("hudi")
    .load("s3://amzn-s3-demo-bucket/myhudidataset") 
    .show()
```

### Amazon EMR 6.6 以前で Scala を使用する場合の読み込み
<a name="scala-read-66"></a>

```
(val snapshotQueryDF = spark.read
    .format("org.apache.hudi")
    .load("s3://amzn-s3-demo-bucket/myhudidataset" + "/*/*"))

snapshotQueryDF.show()
```

### PySpark を使用する場合の読み込み
<a name="pyspark-read"></a>

```
snapshotQueryDF = spark.read \
    .format('org.apache.hudi') \
    .load('s3://amzn-s3-demo-bucket/myhudidataset' + '/*/*')
    
snapshotQueryDF.show()
```

### 増分クエリ
<a name="emr-hudi-incremental-query"></a>

Hudi で増分クエリを実行して、特定のコミットタイムスタンプ以降に変更されたレコードのストリームを取得することもできます。これを行うには、`QUERY_TYPE_OPT_KEY` フィールドを `QUERY_TYPE_INCREMENTAL_OPT_VAL` に設定します。次に、`BEGIN_INSTANTTIME_OPT_KEY` の値を追加して、指定された時刻以降に書き込まれたすべてのレコードを取得します。増分クエリでは、変更されたレコードのみが処理されるため、通常、バッチクエリよりも 10 倍効率が高くなります。

増分クエリを実行するときは、スナップショットクエリに使用されるワイルドカードのアスタリスクを付けずに、ルート (ベース) テーブルパスを使用します。

**注記**  
Presto は増分クエリをサポートしていません。

#### Scala を使用した増分クエリ
<a name="scala-incremental-queries"></a>

```
val incQueryDF = spark.read
    .format("org.apache.hudi")
    .option(DataSourceReadOptions.QUERY_TYPE_OPT_KEY, DataSourceReadOptions.QUERY_TYPE_INCREMENTAL_OPT_VAL)
    .option(DataSourceReadOptions.BEGIN_INSTANTTIME_OPT_KEY, <beginInstantTime>)
    .load("s3://amzn-s3-demo-bucket/myhudidataset")
     
incQueryDF.show()
```

#### PySpark を使用した増分クエリ
<a name="pyspark-incremental-queries"></a>

```
readOptions = {
  'hoodie.datasource.query.type': 'incremental',
  'hoodie.datasource.read.begin.instanttime': <beginInstantTime>,
}

incQueryDF = spark.read \
    .format('org.apache.hudi') \
    .options(**readOptions) \
    .load('s3://amzn-s3-demo-bucket/myhudidataset')
    
incQueryDF.show()
```

Hudi データセットからの読み取りの詳細については、Apache Hudi ドキュメントの「[Querying Hudi tables](https://hudi.apache.org/docs/querying_data.html)」(Hudiテーブルをクエリ) を参照してください。

# Hudi CLI を使用する
<a name="emr-hudi-cli"></a>

Hudi CLI を使用して Hudi データセットを管理し、コミット、ファイルシステム、統計などに関する情報を表示できます。CLI を使用して、手動で圧縮を実行したり、圧縮をスケジュールしたり、スケジュールされた圧縮をキャンセルしたりすることもできます。詳細については、Apache Hudi ドキュメントの「[Interacting via CLI](https://hudi.apache.org/docs/cli/)」を参照してください。

**Hudi CLI を起動してデータセットに接続するには**

1. SSH を使用してマスターノードに接続します。詳細については、「*Amazon EMR 管理ガイド*」の「[SSH を使用してマスターノードに接続する](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-connect-master-node-ssh.html)」を参照してください。

1. コマンドラインで「`/usr/lib/hudi/cli/bin/hudi-cli.sh`」と入力します。

   コマンドプロンプトが `hudi->` に変わります。

1. データセットに接続するには、以下のコマンドを使用します。*s3://amzn-s3-demo-bucket/myhudidataset* は、処理するデータセットへのパスに置き換えます。使用する値は、前の例で設定した値と同じです。

   ```
   connect --path s3://amzn-s3-demo-bucket/myhudidataset
   ```

   以下の例に示すように、コマンドプロンプトが変わって、接続されているデータセットが表示されます。

   ```
   hudi:myhudidataset->
   ```

デフォルトでは、Amazon EMR リリース 7.3.0〜7.8.0 の `hudi-cli.sh` スクリプトは `hudi-cli-bundle.jar` を使用します。問題が発生した場合は、次のコマンドを使用して、従来の Hudi CLI に切り替えることができます。

```
/usr/lib/hudi/cli/bin/hudi-cli.sh --cliBundle false
```

このコマンドは `hudi-cli.sh` スクリプトを実行し、`--cliBundle` フラグを設定し、バンドルされた JAR の代わりに個々の JAR ファイルを使用するように CLI に指示します。デフォルトでは、`--cliBundle` は true に設定されています。つまり、CLI は代わりにバンドルされた JAR を使用します。

## Amazon EMR リリース 7.9.0 以降にはの使用
<a name="emr-hudi-cli-start"></a>

**注記**  
 **hudi-cli.sh** スクリプトは、EMR リリース 7.9.0 以上では廃止されました。Amazon EMR リリース 7.9.0 以降では、**hudi-cli-bundle.jar** を使用しています。

**Hudi CLI を起動してデータセットに接続するには:**

1. SSH を使用してマスターノードに接続します。詳細については、「*Amazon EMR 管理ガイド*」の「[SSH を使用してマスターノードに接続する](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-connect-master-node-ssh.html)」を参照してください。

1. コマンドラインで、「**/usr/lib/hudi/cli-bundle/bin/hudi-cli-with-bundle.sh**」と入力するか、「**hudi-cli-with-bundle**」または「**>hudi-cli**」と入力します。

   コマンドプロンプトが「**hudi- >**」に変わります。

1. データセットに接続するには、以下のコマンドを使用します。**s3://amzn-s3-demo-bucket/myhudidataset** は、処理するデータセットへのパスに置き換えます。使用する値は、前の例で設定した値と同じです。

   ```
   connect --path s3://amzn-s3-demo-bucket/myhudidataset
   ```

1. 以下の例に示すように、コマンドプロンプトが変わって、接続されているデータセットが表示されます。

   ```
   hudi:myhudidataset->
   ```

# Hudi リリース履歴
<a name="Hudi-release-history"></a>

次の表は、Amazon EMR の各リリースに含まれている Hudi のバージョンと、アプリケーションと共にインストールされるコンポーネントを示しています。各リリースのコンポーネントバージョンについては、[Amazon EMR 7.x リリースバージョン](emr-release-7x.md)、[Amazon EMR 6.x リリースバージョン](emr-release-6x.md) または [Amazon EMR 5.x リリースバージョン](emr-release-5x.md) でリリースに応じたコンポーネントバージョンのセクションを参照してください。


**Hudi バージョン情報**  

| Amazon EMR リリースラベル | Hudi バージョン | Hudi でインストールされるコンポーネント | 
| --- | --- | --- | 
| emr-7.12.0 | 1.0.2-amzn-1 | Not available. | 
| emr-7.11.0 | 1.0.2-amzn-0 | Not available. | 
| emr-7.10.0 | 0.15.0-amzn-7 | Not available. | 
| emr-7.9.0 | 0.15.0-amzn-6 | Not available. | 
| emr-7.8.0 | 0.15.0-amzn-5 | Not available. | 
| emr-7.7.0 | 0.15.0-amzn-4 | Not available. | 
| emr-7.6.0 | 0.15.0-amzn-3 | Not available. | 
| emr-7.5.0 | 0.15.0-amzn-2 | Not available. | 
| emr-7.4.0 | 0.15.0-amzn-1 | Not available. | 
| emr-7.3.0 | 0.15.0-amzn-0 | Not available. | 
| emr-7.2.0 | 0.14.1-amzn-1 | Not available. | 
| emr-5.36.2 | 0.10.1-amzn-1 | Not available. | 
| emr-7.1.0 | 0.14.1-amzn-0 | Not available. | 
| emr-7.0.0 | 0.14.0-amzn-1 | Not available. | 
| emr-6.15.0 | 0.14.0-amzn-0 | Not available. | 
| emr-6.14.0 | 0.13.1-amzn-2 | Not available. | 
| emr-6.13.0 | 0.13.1-amzn-1 | Not available. | 
| emr-6.12.0 | 0.13.1-amzn-0 | Not available. | 
| emr-6.11.1 | 0.13.0-amzn-0 | Not available. | 
| emr-6.11.0 | 0.13.0-amzn-0 | Not available. | 
| emr-6.10.1 | 0.12.2-amzn-0 | Not available. | 
| emr-6.10.0 | 0.12.2-amzn-0 | Not available. | 
| emr-6.9.1 | 0.12.1-amzn-0 | Not available. | 
| emr-6.9.0 | 0.12.1-amzn-0 | Not available. | 
| emr-6.8.1 | 0.11.1-amzn-0 | Not available. | 
| emr-6.8.0 | 0.11.1-amzn-0 | Not available. | 
| emr-6.7.0 | 0.11.0-amzn-0 | Not available. | 
| emr-5.36.1 | 0.10.1-amzn-1 | Not available. | 
| emr-5.36.0 | 0.10.1-amzn-1 | Not available. | 
| emr-6.6.0 | 0.10.1-amzn-0 | Not available. | 
| emr-5.35.0 | 0.9.0-amzn-2 | Not available. | 
| emr-6.5.0 | 0.9.0-amzn-1 | Not available. | 
| emr-6.4.0 | 0.8.0-amzn-0 | Not available. | 
| emr-6.3.1 | 0.7.0-amzn-0 | Not available. | 
| emr-6.3.0 | 0.7.0-amzn-0 | Not available. | 
| emr-6.2.1 | 0.6.0-amzn-1 | Not available. | 
| emr-6.2.0 | 0.6.0-amzn-1 | Not available. | 
| emr-6.1.1 | 0.5.2-incubating-amzn-2 | Not available. | 
| emr-6.1.0 | 0.5.2-incubating-amzn-2 | Not available. | 
| emr-6.0.1 | 0.5.0-incubating-amzn-1 | Not available. | 
| emr-6.0.0 | 0.5.0-incubating-amzn-1 | Not available. | 
| emr-5.34.0 | 0.9.0-amzn-0 | Not available. | 
| emr-5.33.1 | 0.7.0-amzn-1 | Not available. | 
| emr-5.33.0 | 0.7.0-amzn-1 | Not available. | 
| emr-5.32.1 | 0.6.0-amzn-0 | Not available. | 
| emr-5.32.0 | 0.6.0-amzn-0 | Not available. | 
| emr-5.31.1 | 0.6.0-amzn-0 | Not available. | 
| emr-5.31.0 | 0.6.0-amzn-0 | Not available. | 
| emr-5.30.2 | 0.5.2-incubating | Not available. | 
| emr-5.30.1 | 0.5.2-incubating | Not available. | 
| emr-5.30.0 | 0.5.2-incubating | Not available. | 
| emr-5.29.0 | 0.5.0-incubating | Not available. | 
| emr-5.28.1 | 0.5.0-incubating | Not available. | 
| emr-5.28.0 | 0.5.0-incubating | Not available. | 