Ma tâche AWS Glue échoue avec une perte de nœuds lors de la migration d'un ensemble de données volumineux d'Amazon RDS vers Amazon S3.

Date de la dernière mise à jour : 04/09/2020

Je migre un ensemble de données volumineux d'Amazon Relational Database Service (Amazon RDS) ou d'une base de données JDBC sur site vers Amazon Simple Storage Service (Amazon S3) en utilisant AWS Glue. L'exécution de ma tâche ETL dure longtemps. Ensuite, elle échoue avec une perte de nœuds.

Brève description

AWS Glue utilise une connexion unique pour lire la totalité de l'ensemble de données. Si vous migrez une grande table JDBC, la tâche ETL peut s'exécuter longtemps, sans signe d'avancement du côté d'AWS Glue. La tâche peut finalement échouer suite à des problèmes d'espace disque (perte de nœuds). Pour résoudre ce problème, lisez la table JDBC en parallèle. Si la tâche échoue toujours avec une perte de nœuds, utilisez une expression SQL comme prédicat pushdown.

Solution

Utilisez une ou plusieurs des méthodes suivantes pour résoudre les erreurs de nœud perdues pour les ensembles de données JDBC.

Lire la table JDBC en parallèle

Si la table n'a pas de colonnes numériques (INT ou BIGINT), utilisez l'option hashfield pour partitionner les données. Affectez à hashfield le nom d'une colonne de la table JDBC. Pour obtenir des résultats optimaux, choisissez une colonne avec une distribution uniforme des valeurs.

Si la table contient des colonnes numériques, définissez les options hashpartitions et hashexpression dans la table ou pendant la création du DynamicFrame :

  • hashpartitions : définit le nombre de tâches qu'AWS Glue crée pour lire les données.
  • hashexpression : divise les lignes de manière uniforme entre les tâches.

Voici un exemple de définition de hashpartitions et hashexpression lors de la création d'un DynamicFrame en utilisant une connexion JDBC. Dans connection_option, remplacez l'URL JDBC, le nom d'utilisateur, le mot de passe, le nom de table et le nom de colonne.

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")

Voici un exemple de définition de hashpartitions et hashexpression lors de la création d'un DynamicFrame depuis le catalogue AWS Glue :

datasource0 = glueContext.create_dynamic_frame.from_catalog(database = "your_database", table_name = "your_table",additional_options={"hashexpression":"column_name","hashpartitions":"10"}, transformation_ctx = "datasource0")

Remarque : la définition de valeurs plus élevées pour hashpartitions peut réduire les performances de votre table. Cela s'explique par le fait que chaque tâche lit la totalité de la table, puis renvoie un ensemble de lignes à l'exécuteur.

Pour plus d'informations, consultez Lecture des tables JDBC en parallèle.

Utiliser une expression SQL comme prédicat pushdown

Remarque : l'expression SQL suivante ne fonctionne pas comme prédicat pushdown pour les bases de données Oracle. Cependant, elle fonctionne comme prédicat pushdown pour toutes les autres bases de données prises en charge en natif par AWS Glue (Amazon Aurora, MariaDB, Microsoft SQL Server, MySQL et PostgreSQL).

Si la table contient des milliards d'enregistrements et des tébioctets (Tio) de données, l'exécution de la tâche peut durer longtemps ou échouer, même après avoir défini hashpartitions et hashexpression. Pour résoudre ces problèmes, utilisez une expression SQL similaire à celle ci-dessous avec l'option hashexpression  :

column_name > 1000 AND column_name < 2000 AND column_name

L'expression SQL fait office de prédicat pushdown. Elle force la tâche à lire un ensemble de lignes chaque fois qu'elle s'exécute au lieu de lire toutes les données à la fois. L'instruction complète se présente comme suit :

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")

Remarque : veillez à désactiver les signets de tâche pour les exécutions de tâche initiales avec cette configuration. Lorsque vous exécutez une tâche avec un signet de tâche, AWS Glue enregistre la valeur maximale de la colonne. Lorsque vous exécutez de nouveau la tâche, AWS Glue traite uniquement les lignes qui ont des valeurs supérieures à la valeur de signet précédente. Vous pouvez activer les signets de tâche au cours de la dernière exécution de tâche, si nécessaire.