Faîtes vos premiers pas avec Apache PIG

Godson K. Kalipe
TakwimuLab
Published in
10 min readOct 12, 2020

Apache Pig, qu'est ce que c'est ?

Au commencement(en 2005) était Hadoop (HDFS, YARN, MapReduce). Initialement plébiscité par tous comme le sauveur des entreprises croulant sous le poids de leur données, MapReduce se révèle pourtant très vite extrêmement verbeux. Naissent alors une panoplie de solutions qui veulent permettre d'exécuter des jobs MapReduce en fournissant moins d'efforts. Dans cette ruée, Apache Pig est l'un des premiers outils à rejoindre la flotte Hadoop, en 2008, avec pour objectif de :

  • offrir un nouveau langage -PigLatin- similaire à du SQL, plus facile (et surtout plus rapide) à écrire, à comprendre et à débugger que les mappers et reducers Java.
  • fournir un moyen d'interagir interactivement avec les données HDFS à travers le grunt de Pig. Ce grunt permet d'interagir avec des données HDFS interactivement à travers un prompt similaire à un prompt SQL ou python.
  • permettre un traitement encore plus rapide des données (puisque aujourd'hui, Pig peut tourner sur Apache Tez ou Spark qui offrent des performances supérieures à celles de MapReduce)

Apache Pig fonctionne donc "au-dessus" de MapReduce comme le montre son architecture (voir image suivante). Concrètement, cela veut dire que les instructions PigLatin sont parsées, optimisées puis "converties" en fonctions mappers et reducers qui sont exécutées sur les données.

Architecture de Apache Pig

Apache Pig peut être utilisé de trois manières :

  • À travers le grunt Pig similaire qui est accessible à travers la commande "pig". Grâce à ce prompt, on peut exécuter une requête à la fois sur les données HDFS.
Grunt Apache Pig
  • En rédigeant des scripts PigLatin dans des fichiers avec l'extension ".pig" qui peuvent être exécutés depuis un terminal.
  • En utilisant une outil web d'administration de Hadoop du style Apache Ambari ou Hue. Apache Ambari. Apache Ambari est un outil de gestion de cluster Hadoop qui permet d’avoir une vue d’ensemble de tous les services d’un cluster Hadoop au travers d’une interface web. Il offre par ailleurs, une interface semblable à un IDE dans lequel peuvent être écrits et exécutés des scripts Pig.
Éditeur Hue pour Pig | Source : Kannandreams.wordpress.com

PigLatin

PigLatin est le langage utilisé par Pig pour analyser les données HDFS. Sa structure de données principales est la relation qui est une collection de tuples. Un tuple lui même est un ensemble de valeurs typées et groupées ensemble dans un ordre précis. Les types disponibles en PigLatin sont similaires à ceux que l'on retrouve dans n’importe quel Système de Gestion de Base Données variant des plus simples int, long, Boolean à ceux plus complexes comme Bag ou Map.

Un script Pig est constitué d’une série de déclarations similaires à des requêtes SQL, qui sont exécutés séquentiellement. Chaque déclaration reçoit une relation en entrée et en retourne une autre en sortie.

Passons à présent en revue quelques uns des opérateurs relationnels utilisés pour construire les déclarations constituant un script Pig. Il existe une vingtaine d'opérateurs répartis en 6 catégories :

  • Les opérateurs de chargement et de sauvegarde

LOAD : Il permet de charger les données d’un fichier local ou HDFS dans une relation Pig.

STORE : Cet opérateur permet d’enregistrer une relation Pig dans un fichier.

  • Les opérateurs de filtrage :

FILTER : Il permet d’éliminer certains tuples d’une relation sur le critère d’une valeur donnée.

DISTINCT : permet d’éliminer les doublons d’une relation.

FOREACH, GENERATE : permet de générer une nouvelle relation en appliquant une transformation à chaque tuple d’une relation existante.

  • Les opérateurs de groupage et de jointure :

JOIN : permet de joindre deux relations similairement à ce qui se fait en SQL.

GROUP : permet de grouper les données dans une relation unique.

CROSS : Permet de créer un produit cartésien de deux ou plusieurs relations.

  • Les opérateurs de tri :

ORDER : permet de trier les tuples d’une relation grâce aux valeurs d’une ou plusieurs colonnes.

LIMIT : permet de ne récupérer qu’un nombre limité de tupes (semblable à SQL)

  • Les opérateurs de combinaison et de division :

UNION : Il permet de combiner deux relations en une seule (similaire à SQL)

SPLIT : Permet de diviser une relation en deux autres relations

  • Les opérateurs de diagnostic :

DUMP : affiche le contenu d’une relation directement dans la console (en utilisant le grunt Pig)

DESCRIBE : décrit le schéma d’une relation.

PS : Cette revue initiale est faite à titre de référence. Il est normal que vous n'y compreniez pas grand chose et des exemples pratiques de leur utilisation sur des données réelles seront présentées dans les sections suivantes.

Si PigLatin peut paraître limité en terme d’opérateurs, il faut noter qu’il est facilement extensible par des fonctions customisées définies par l’utilisateur (UDF pour User Defined Functions) qui peuvent être écrites en Java, Python ou Ruby et directement appelées depuis un script PigLatin.

Installation de Pig sur Ubuntu 16.04/18.04/20.04

Étant donné que Pig fonctionne grâce à MapReduce, ce-dernier est un pré-requis pour l'installation décrite dans cette section. En supposant que vous avez déjà installé Hadoop sur votre machine (le cas échéant, j'ai un article qui vous explique comment ici), pour installer Pig, les étapes sont les suivantes :

  • Télécharger et décompresser Pig (préférablement dans le dossier home de votre utilisateur dédié à Hadoop — /home/hdoop, chez moi) :
$ wget https://downloads.apache.org/pig/pig-0.17.0/pig-0.17.0.tar.gz$ tar -xzf pig-0.17.0.tar.gz
  • Ensuite, définir les variables d'environnement liées à Pig. Pour cela exécutez la commande :
$ gedit ~/.bashrc

Puis, ajouter à la fin du fichier, les lignes suivantes :

#Set PIG_HOMEexport PIG_HOME=/home/hdoop/pig-0.17.0export PATH=$PATH:/home/hdoop/pig-0.17.0/binexport PIG_CLASSPATH=$HADOOP_CONF_DIR

Ensuite, pour valider ces changements, exécuter la commande :

$ source ~/.bashrc
  • Vérifiez que l'installation est effective avec :
$ pig -version

Vous devriez avoir une sortie vous montrant que la version 0.17.0 est effectivement installée sur votre machine.

Prise en main de Apache Pig

Dans cette section, nous allons passer en revue concrètement quelques uns des opérateurs clés de Apache avant et finir par un exercice d'application fort sympatique pour expérimenter la puissance de Pig.

Mais d'abord, nous devons télécharger les données sur lesquelles nous allons travailler : le dataset de films IMDB.

$ wget https://datasets.imdbws.com/title.basics.tsv.gz
$ gunzip title.basics.tsv.gz
$ wget https://datasets.imdbws.com/title.ratings.tsv.gz
$ gunzip title.ratings.tsv.gz

Les deux fichiers correspondent respectivement aux descriptions et métadonnées de films (entre autres types de divertissements) et les notes attribuées par le public à ces films.

Pour faciliter le traitement avec Pig, nous allons faire une copie de ces fichiers de laquelle, nous allons retirer la première ligne correspondant à l'entête du fichier qui ne nous intéresse pas.

$ cp titles.basics.tsv titles.tsv
$ cp titles.ratings.tsv ratings.tsv
#On supprime les premières lignes des fichiers
$ sed -i '1d' titles.tsv
$ sed -i '1d' ratings.tsv

Il est à noter que les manipulations précédentes peuvent se faire avec Pig mais qu'elles rendraient inutilement complexe cette introduction à PigLatin. Si vos fichiers sont prêts, vous êtes prêts à vous attaquer à vos premières instructions PigLatin maintenant!

Revue pratique des commandes PigLatin

Le grunt Pig

Avant de commencer, il est important de noter que Apache Pig dispose de deux modes d'exécution : le mode local et le mode MapReduce. Comme l'indiquent leurs noms, dans le premier mode, Pig attend des données de la machine locale et dans le second cas, des données HDFS.

Dans notre exemple, nous allons travailler avec des fichiers locaux, c'est pourquoi il est important de préciser cela lorsque nous accédons au grunt Pig par la commande $ pig -x local .Au cas où nos données se situeraient sur HDFS, la commande serait $ pig -x mapreduce . Il faut aussi noter que quand on exécute la commande $ pig sans précision, le mode d'exécution par défaut est mapreduce.

Allez, on y va!

LOAD | LIMIT | DUMP

Nous commençons par la série de commandes : LOAD, LIMIT, DUMP. La commande LOAD sert à charger des données dans une relation Pig en en spécifiant le schéma. LIMIT permet de créer une nouvelle relation qui ne contient que les n premiers tuples d'une autre relation. Enfin DUMP affiche les résultats dans la console.

grunt> ratings = LOAD '/home/hdoop/imdb/ratings.tsv' AS  (movieID:chararray, averageRating:float, numVotes:long);
grunt> ratings5 = LIMIT ratings 5;
grunt> DUMP ratings5;

Cette série d’instructions PigLatin nous donne donc le résultat suivant en console.

(tt0000001,5.6,1650)
(tt0000002,6.1,199)
(tt0000003,6.5,1359)
(tt0000004,6.2,121)
(tt0000005,6.2,2144)

Je vous encourage à essayer ces commandes sur votre machine si votre installation Pig a été réussie. Si vous obtenez une erreur liée au fait que le chemin spécifié n'existe pas sur HDFS, assurez-vous que vous exécutez bien Pig en mode local.

GROUP relation BY colonne

GROUP BY permet de grouper les tuples d'une relation en groupes de tuples selon qu'ils partagent ou non, la même valeur pour une colonne spécifiée.

grunt> mongroupe = GROUP ratings5 BY averageRating;grunt> DUMP mongroupe;

Ainsi, quand on groupe la relation ratings5 par rapport à la colonne averageRating, on obtient le résultat suivant :

(5.6,{(tt0000001,5.6,1650)})
(6.1,{(tt0000002,6.1,199)})
(6.2,{(tt0000005,6.2,2144),(tt0000004,6.2,121)})
(6.5,{(tt0000003,6.5,1359)})

DESCRIBE

L'opérateur DESCRIBE permet de prendre connaissance du schéma d'une relation.

grunt> DESCRIBE mongroupe;

La commande précédente donne donc le schéma de la nouvelle relation mongroupe. Il faut ici noter l'apparition du type group spécialement utilisé pour identifier les colonnes sur lesquelles une aggrégation a été pratiquée pour obtenir la relation que l'on observe.

mongroupe: {group: float,ratings5: {(movieID: chararray,averageRating: float,numVotes: long)}}

FILTER relation BY expression booléenee

FILTER BY, semblable à un SELECT de SQL, permet de sélecionner uniquement certains tuples d'une relation pour lesquelles une expression booléenne est évaluée à "vrai".

grunt> y = FILTER ratings5 BY averageRating > 6;grunt> DUMP y;

On peut ainsi spécifier qu'on ne veut voir que les films ayant une note moyenne supérieure à 6 et ainsi, la relation résultante y ne contiendra que les 4 tuples respectant la condition spécifiée.

(tt0000002,6.1,199)
(tt0000003,6.5,1359)
(tt0000004,6.2,121)
(tt0000005,6.2,2144)

Vous devez maintenant avoir une idée plus claire de comment fonctionnent les opérateurs relationnels PigLatin. Une utilisation du grunt Pig comme nous venons de le faire nous permet d'obtenir un rapide aperçu des données. Mais pour exécuter des jobs plus lourds, on a en général recours aux scripts Pig. On explore cela avec notre prochain exercice.

On se fait pas une petite soirée ciné ? [Exercice]

Alors, c'est samedi soir et vous êtes d'humeur à vous faire une petite soirée ciné rétro de qualité ? Pas de panique, Apache Pig à la rescousse. 🤓

Pour notre exercice d'application, supposons que nous avons à notre disposition le même dataset IMDB et que nous désirons trouver quels sont les 5 vieux films les mieux notés du dataset.

On commence par créer un script pig avec :

$ nano oldest5StarMovies.pig

Son contenu va être le suivant :

 --Nous chargeons les notes des films dans la relation ratingsratings = LOAD ‘/home/hdoop/imdb/ratings.tsv’ AS (movieID:chararray, averageRating:float, numVotes:long);--Ensuite, on charge les films eux-même das la relation moviesmovies = LOAD ‘/home/hdoop/imdb/titles.tsv’ AS (movieID:chararray, titleType:chararray, primaryTitle:chararray, originalTitle:chararray, isAdult:Boolean, startYear:long, endYear:chararray, runMinutes:int, genres:chararray);--On joint les deux relations sur la base commune de l’id du filmratedMovies = JOIN ratings BY movieID, movies BY movieID;--On ne sélectionne que les films ayant été notés plus de 8/10fiveStarMovies = FILTER ratedMovies BY (averageRating > 8.0) AND (titleType == ‘movie’);--Parce que le dataset contient des doublons, on s’assure de ne récupérer chaque film q’une seule foisuniqueFiveStarMovies = DISTINCT fiveStarMovies;--On ne retient que les colonnes que l’on affiche dans le résultatfiveStarMoviesCrisp = FOREACH uniqueFiveStarMovies GENERATE titleType, primaryTitle, genres, startYear, averageRating, numVotes;--On trie le résultat par ordre descendant pour avoir les meilleurs films en têteoldestFiveStarMovies = ORDER fiveStarMoviesCrisp BY movies::startYear ASC;--On affiche uniquement les 10 films les mieux notéstopOldestFiveStarMovies = LIMIT oldestFiveStarMovies 10;DUMP topOldestFiveStarMovies;

Le script est suffisamment bien commenté pour se passer d'explications supplémentaires. Cependant, il est important de revenir sur quelques notions qui pourraient confondre un débutant :

  • Les deux tirets "- -" marquent le début d'un commentaire en PigLatin
  • L'opérateur FOREACH effectue des projections du style SQL. L'instruction FOREACH relation1 GENERATE x1, x2,…,xn, génère une nouvelle relation ayant le même nombre de lignes que relation1 mais dans laquelle, les tuples ne sont constitués que des champs x1 à xn.

On exécute ensuite le script avec la commande suivante :

$ pig -x local oldest5StarMovies.pig

Une fois exécuté (ce qui devrait prendre entre 1 et 5 minutes selon la performance de votre machine), vous obtiendrez le résultat suivant :

(movie,Love: Dashuri,Romance,,8.1,11)
(movie,Life Without Hope,Action,,9.0,9)
(movie,Însir’te margarite,\N,1911,9.0,10)
(movie,Ayastefanos’taki Rus abidesinin yikilisi,Documentary,1914,8.8,223)
(movie,Tillie’s Tomato Surprise,Comedy,1915,8.3,25)
(movie,The Eternal Sappho,Drama,1916,9.2,5)
(movie,On Dangerous Ground,Drama,War,1917,8.8,94)
(movie,Alimony,Drama,1917,8.2,6)
(movie,Runaway Romany,Drama,Romance,1917,8.6,80)
(movie,Masked Ball,\N,1917,9.3,6)

Et Voilouuuu ! Vous avez de quoi vous occuper! Depuis les films romantiques aux documentaires en passant par les films d'action, une fine sélection du meilleur cinéma vintage pour passer une bonne soirée.

PigLatin, quand y en a plus ? Et ben, y en a encore!

Vous en savez déjà suffisamment à ce point pour rédiger vos propres scripts PigLatin avec l'aide de la documentation PigLatin. je tenais cependant à terminer en parlant des fonctions et commandes de Pig. À part les opérateurs relationnels, Pig dispose également de différentes types de fonctions.

  • Les fonctions d’évaluation : MAX, MIN, SUM, AVG…
  • Les fonctions de chargement : PigStorage(), TextLoader() qui sont utilisées pour charger des données de différents types (différents des fichiers .tsv telles que les fichiers .txt ou .csv)
  • Les fonctions de sacs et de tuples : TOBAG(), TOP() pour aggréger ensemble des tuples en bags (liste de tuples similaires à celles obtenues avec GROUP BY)
  • Les fonctions de chaînes de charactère : ENDSWITH(), STARTSWITH(), SUBSTRING()
  • Les fonctions de date : ToDate(), CurrentTime(), GetDay()
  • Les fonctions mathématiques : ABS(), ASIN(), RANDOM()
  • Les fonctions customisées UDF : Elles peuvent être écrites en Java (entre autres langages) et importées comme des .jar dans PigLatin pour en étendre les possibilités.

PigLatin possède également des commandes shell dont je présente ici quelques unes.

  • grunt> history : pour afficher les dernieres commandes Pig entrées
  • grunt> quit : permet de quitter le grunt Pig
  • grunt> exec : permet d’exécuter un script Pig
  • grunt> sh ls : permet d’afficher les fichier du répertoire courant
  • grunt> fs -ls : affiche les fichiers présents à la racine de HDFS

Ce sera tout pour cet article! J'espère que cette introduction à Apache Pig vous aura permis de mieux saisir de quoi il s'agit, comment cela fonctionne et ce que l'on peut faire avec dans un environnement Hadoop.

L'absence criarde de ressources compréhensives et simples à comprendre (en français et même en anglais d'ailleurs) est ma motivation principale pour rédiger ces tutoriels d'introduction aux technologies de Hadoop. Vos retours (positifs comme négatifs) sur l'article sont donc vivement encouragés afin que je puisse détecter plus facilement ce qui pourrait être amélioré, ajouté ou racourci afin de produire des articles plus utiles. Merci d'avance!

Le prochain article va parler de bases de données relationnelles en Hadoop notamment de Hive et de SQOOP!

À très vite!

--

--