AWS Glue を使い、Amazon Relational Database Service (Amazon RDS) あるいはオンプレミスの JDBC データベースから、Amazon Simple Storage Service (Amazon S3) に大規模なデータセットを移行しています。ETL ジョブが長時間実行された後、ノードが失われて失敗します。
簡単な説明
AWS Glue は 1 つの接続でデータセット全体を読み込みます。大規模な JDBC テーブルを移行する場合、ETL ジョブは、 AWS Glue 側の進捗情報を得られないまま長期間にわたり処理しつづけます。そのためジョブは、ディスク容量不足 (ノード欠損) として処理に失敗します。この問題を解決するには、JDBC テーブルを並列で読み込むようにします。それでもノード欠損での処理失敗が解決しない場合は、SQL 式にプッシュダウン述語を使用します。
解決方法
JDBC データセットのノード欠損エラーを解決するには、次のいずれかの方法を使用します。
JDBC テーブルを並列で読み込む
テーブルに数値列 (INT または BIGINT) がない場合は、hashfield オプションでデータを分割します。JDBC テーブル内の列の名前に hashfield を設定します。最良の結果を得るには、値が均等に分散されている列を選択するようにします。
テーブルに数値列がある場合は、テーブル内に、もしくは DynamicFrame の作成中にhashpartitions と hashexpression オプションを定義します。
- hashpartitions は、データ読み込みを行うために AWS Glue が作成するタスクの数を定義します。
- hashexpression は、タスク間で均等に行を分割します
JDBC 接続を使用して DynamicFrame を作成する間に、hashpartitions と hashexpression の設定をする例を次に示します。connection_option で、JDBC URL、ユーザー名、パスワード、テーブル名、およびカラム名を置き換えます。
connection_option= {"url": "jdbc:mysql://mysql–instance1.123456789012.us-east-1.rds.amazonaws.com:3306/database", "user": "your_user_name", "password": "your_password","dbtable": "your_table","hashexpression":"column_name","hashpartitions":"10"}
datasource0 = glueContext.create_dynamic_frame.from_options('mysql',connection_options=connection_option,transformation_ctx = "datasource0")
AWS Glue カタログから DynamicFrame を作成する間に、hashpartitions と hashexpression の設定をする例を次に示します。
datasource0 = glueContext.create_dynamic_frame.from_catalog(database = "your_database", table_name = "your_table",additional_options={"hashexpression":"column_name","hashpartitions":"10"}, transformation_ctx = "datasource0")
注: hashpartitions により大きな値を設定すると、テーブルのパフォーマンスが低下する場合があります。これは、各タスクがテーブル全体を読み込み、複数行をまとめてエグゼキュータに返すからです。
詳細については、「JDBC テーブルからの並列読み取り」をご参照ください。
SQL 式でプッシュダウン述語を使用する
注意: 次の SQL 式は、Oracle データベースのプッシュダウン述語としては機能しません。ただし、この式は、AWS Glue (Amazon Aurora、MariaDB、Microsoft SQL Server、MySQL、PostgreSQL) でネイティブにサポートされている他のすべてのデータベースのプッシュダウン述語としては機能します。
hashpartitions や hashexpression の設定を行っても、テーブルに数十億のレコードやテビバイト (TiB) 級のデータが含まれている場合は、ジョブの処理完了に長い時間がかかったり、ノード欠損で失敗することがあります。これらの問題を解決するには、 hashexpression オプションを使い SQL 式を次のようにします。
column_name > 1000 AND column_name < 2000 AND column_name
SQL 式は プッシュダウン述語として機能し、ジョブは一度にすべてのデータを読み込まず、強制的に 1 回の実行で 1 行のセットを読み込むようになります。完全なステートメントは次のようになります。
datasource0 = glueContext.create_dynamic_frame.from_catalog(database = "sampledb", table_name = "test_table",additional_options={"hashexpression":"column_name > 1000 AND column_name < 2000 AND column_name","hashpartitions":"10"}, transformation_ctx = "datasource0")
注意: この設定で最初にジョブを実行する際は、 ジョブブックマークを無効にしていることを確認してください。ジョブブックマークを使いジョブを実行すると、AWS Glue では列の最大値だけ記録します。ジョブを再度実行しても、以前のブックマークより大きい値を含む行のみが、AWS Glue で処理されます。必要に応じて、最後のジョブ実行中にジョブのブックマークを有効にできます。
関連情報
AWS Glue ジョブで「Exit status:-100.Diagnostics: Container released on a *lost* node」エラーが発生して失敗するのはなぜですか?
AWS Glue データカタログでの接続を定義する