Vous êtes sur la page 1sur 50

Spark

Table des matières


1 Spark Overview ................................................................................................................................ 2
1.2 PySpark est une interface pour Apache Spark en Python .................................................................. 3
1.3 Terminologies ....................................................................................................................... 3
1.4 Comparaison avec Hadoop ........................................................................................................ 4
1.5 Principales différences entre Hadoop et Spark ............................................................................... 5
1.6 Idées fausses sur Hadoop et Spark .............................................................................................. 10
1.7 Cas d'utilisation Hadoop et Spark .............................................................................................. 11
1.8 Hadoop ou Spark ? .................................................................................................................. 11
2 Utiliser Spark ................................................................................................................................. 13
2.1 Preparation de l'environnement ................................................................................................ 13
2.2 Soumettre une tâche au cluster Spark en mode Local .................................................................... 16
2.3 Démarrage un cluster en mode StandAlone ................................................................................. 18
2.4 Soumettre une tâche au cluster Spark en mode StandAlone ............................................................ 20
2.5 Installation de Pyspark dans Anaconda ....................................................................................... 21
2.6 Premier exemple "WordCount" ................................................................................................ 22
3 Resilient Distributed Dataset(RDD) ..................................................................................................... 24
3.1 Caractéristiques de Resilient Distributed Dataset (RDD) ................................................................. 24
3.2 Comparaison : RDD vs Dataset vs DataFrame............................................................................... 25
3.5 Limitations du RDD dans Apache Spark ..................................................................................... 37
4 Pyspark SQL &DataFrame ................................................................................................................ 39
4.1 Point de départ : SparkSession .................................................................................................. 39
4.2 Créer des DataFrames .............................................................................................................. 40
4.3 Operations & requêtes.............................................................................................................. 44
4.4 Agrégation des données ........................................................................................................... 45
4.5 UDF user defined function ....................................................................................................... 46
4.6 Nettoyage des données ............................................................................................................. 47
4.7 Entrée/sortie de données ........................................................................................................... 50
1 Spark Overview
1.1 Apache Spark

«
What is Apache Spark™?

Apache Spark™ is a multi-language engine for executing data engineering, data science, and machine learning on
single-node machines or clusters.
»

Apache Spark est un moteur d'analyse unifié pour le traitement de données à grande échelle. Il fournit des API de haut
niveau en Java, Scala, Python et R, ainsi qu'un moteur optimisé prenant en charge les graphiques d'exécution. Il
prend également en charge un riche ensemble d'outils de niveau supérieur, notamment Spark SQL pour SQL et le
traitement des données structurées, MLlib pour l'apprentissage automatique, GraphX pour le traitement des graphes
et Structured Streaming pour le calcul incrémentiel etle traitement des flux.

Apache Spark a débuté en tant que projet de recherche à l'AMPLab de l'UC Berkeley en 2009 et était opensource au
début de 2010. De nombreuses idées derrière le système ont été présentées dans divers documents de recherche au fil
des ans.

Après sa sortie, Spark est devenu une vaste communauté de développeurs et a rejoint Apache SoftwareFoundation en
2013. Aujourd'hui, le projet est développé en collaboration par une communauté de centaines de développeurs issus de
centaines d'organisations.

Il est conçu pour des performances rapides et utilise la RAM pour la mise en cache et le traitement desdonnées.

Spark exécute différents types de charges de travail Big Data. Cela inclut le traitement par lots de type MapReduce,
ainsi que le traitement de flux en temps réel, l'apprentissage automatique, le calcul de grapheset les requêtes
interactives. Avec des API de haut niveau faciles à utiliser, Spark peut s'intégrer à de nombreuses bibliothèques
différentes, notamment PyTorch et TensorFlow. (Ce sont deux bibliothèques de
Deep Learning)

Le moteur Spark a été créé pour améliorer l'efficacité de MapReduce et conserver ses avantages. Même si Spark n'a pas
son système de fichiers, il peut accéder aux données sur de nombreuses solutions de stockage différentes. La
structure de données utilisée par Spark est appelée Resilient Distributed Dataset,ou RDD.

Spark est un moteur de traitement rapide et général compatible avec les données Hadoop. Il peut s'exécuterdans des
clusters Hadoop via YARN ou le mode standalone de Spark, et il peut traiter des données dans HDFS, HBase,
Cassandra, Hive et n'importe quel format d'entrée Hadoop. Il est conçu pour effectuer à la foisun traitement par lots (batch
processing, similaire à MapReduce) et de nouvelles charges de travail telles que le streaming, les requêtes interactives
et l'apprentissage automatique.

Spark est considéré souvent comme un nouveau cadre de calcul dans l'écosystème de Hadoop. Bien sûr, ilpeut être
déployé seul sans Hadoop, et on le verra plus tard.

Il existe cinq composants principaux d'Apache Spark :


Apache Spark Core: La base de tout le projet. Spark Core est responsable des fonctions nécessaires telles
que la planification, la répartition des tâches, les opérations d'entrée et de sortie, la récupération des pannes, etc.
D'autres fonctionnalités sont construites par-dessus.
Spark Streaming: Ce composant permet le traitement des flux de données en direct. Les données
peuvent provenir de nombreuses sources différentes, notamment Kafka, Kinesis, Flume, etc.
Spark SQL: Spark utilise ce composant pour collecter des informations sur les données structurées et surla manière
dont les données sont traitées.
Bibliothèque de Machine Learning (MLlib): Cette bibliothèque se compose de nombreux algorithmes d'apprentissage
automatique. L'objectif de MLlib est l'évolutivité et de rendre l'apprentissage automatique
plus accessible.
GraphX: Ensemble d'API utilisées pour faciliter les tâches d'analyse de graphes.

1.2 PySpark est une interface pour Apache Spark en Python

PySpark est une interface pour Apache Spark en Python. Il vous permet non seulement d'écrire des applications Spark à
l'aide des API Python, mais fournit également le shell PySpark pour analyser de manière interactive vos données dans
un environnement distribué. PySpark prend en charge la plupart desfonctionnalités de Spark telles que Spark SQL,
DataFrame, Streaming, MLlib (Machine Learning) et Spark Core.

1.3 Terminologies

Apache Spark - Une plate-forme de traitement de données open source conçue pour le traitement à grandevitesse en
mémoire. Pensé comme une alternative à MapReduce. Spark peut être une implémentation à un ou plusieurs nœuds.
Resilient Distributed Dataset — Également appelé RDD. C'est un jeu de données immuable. Cela signifie qu'il ne peut
pas être modifié au fil du temps. Les RDD peuvent être stockés sur disque ou en mémoire dansun cluster. Ils sont
tolérants aux pannes. Les modifications apportées aux RDD sont effectuées avec les opérations de transformation et
d'action.
Partition — Les données peuvent être réparties en unités logiques plus petites. Ces unités sont appeléespartitions.
Cluster Manager — Un service externe comme Yarn, Apache Mesos ou Spark Standalone Cluster. Lesgestionnaires de
cluster assurent la surveillance, la planification et la sécurité.
Worker Node — Également appelé nœud esclave. Les exécuteurs sont des nœuds de travail générés pendant la durée de
vie d'une application Spark. Le travail d'exécution sur les données dans le nœud et lerapport au nœud maître.
Application — Un programme d'utilisateurs construit sur le cluster Spark. Il se compose d'un programmepilote et des
exécuteurs sur le cluster.
Executor — Existent généralement sur un nœud de travail et implémentent des tâches. Ces tâches sont en mémoire ou sur
disque. Les tâches sont créées par le pilote et envoyées aux exécuteurs. Lorsque les exécuteurs ont terminé la tâche, ils
renvoient les résultats au pilote.
Driver Program — Un programme qui s'exécute sur un nœud maître. Il crée le SparkContext. Ils déclarent des
Transformations et des Actions sur le RDD’. C'est le processus où s'exécute la fonction Main(). Il convertitles processus
en tâches qui sont ensuite exécutées sur les exécuteurs.
Transformations - Les transformations créent de nouveaux RDD en fonction des opérations effectuées sur les RDD
existants. Il existe deux types de transformations : étroites et étendues.
Narrow Transformations — Tous les éléments requis pour calculer une partition vivent dans une partitionparent unique
d'un RDD.
Wide Transformations — Tous les éléments requis pour calculer une partition appartiennent à plusieurs partitions d'un
RDD.
Actions — Les actions sont des opérations qui produisent des valeurs non RDD. Ils déclenchent des transformations pour
renvoyer des valeurs. Exemples d'actions : compter, collecter, agréger, min, max oupremier.

1.4 Comparaison avec Hadoop

Aujourd'hui, nous avons de nombreuses solutions gratuites pour le traitement du Big Data. De nombreusesentreprises
proposent également des fonctionnalités d'entreprise spécialisées pour compléter les plates- formes open source.

L'écosystème Hadoop
Hadoop prend en charge l'analyse avancée des données stockées (par exemple, l'analyse prédictive, l'exploration de
données, l'apprentissage automatique (ML), etc.). Il permet de diviser les tâches de traitement d'analyse de données
volumineuses en tâches plus petites. Les petites tâches sont effectuées enparallèle à l'aide d'un algorithme (par
exemple, MapReduce), puis sont réparties sur un cluster Hadoop (c'est-à-dire des nœuds qui effectuent des calculs
parallèles sur de grands ensembles de données).

Chaque machine d'un cluster stocke et traite les données. Hadoop stocke les données sur des disques à l'aide de
HDFS. Le logiciel offre des options d'évolutivité transparentes. Vous pouvez commencer avec une seule machine,
puis passer à des milliers, en ajoutant n'importe quel type de matériel d'entreprise ou de base.

L'écosystème Hadoop se compose de quatre modules principaux :


Hadoop Distributed File System (HDFS) : système de stockage de données principal qui gère de grands ensembles de
données exécutés sur du matériel standard. Il fournit également un accès aux données à hautdébit et une tolérance élevée
aux pannes.
Yet Another Resource Negotiator (YARN) : gestionnaire de ressources de cluster qui planifie les tâches etalloue des
ressources (par exemple, le processeur et la mémoire) aux applications.
Hadoop MapReduce : divise les tâches de traitement de données volumineuses en tâches plus petites,distribue les petites
tâches sur différents nœuds, puis exécute chaque tâche.
Hadoop Common (Hadoop Core) : ensemble de bibliothèques et d'utilitaires communs dont dépendent les trois autres
modules.

1.5 Principales différences entre Hadoop et Spark

Les sections suivantes décrivent les principales différences et similitudes entre les deux cadres. Nousexaminerons
Hadoop contre Spark sous plusieurs angles. Certains d'entre eux sont le coût, les performances, la sécurité et la
facilité d'utilisation.

Le tableau ci-dessous donne un aperçu des conclusions tirées dans les sections suivantes.

Catégorie de
comparaison Hadoop Spark
Hadoop Spark

Performances plus lentes, utilisedes


Performances rapides en mémoire avec
disques pour le stockage etdépend
Performances réduction des opérations de lecture et
de la vitesse de lecture etd'écriture du
d'écriture sur disque.
disque.

Une plate-forme open-source,


moins coûteuse à faire Une plate-forme open-source, mais s'appuiesur la
fonctionner. mémoire pour le calcul, ce qui augmente
Coût
Utilise du matériel abordable. considérablement les coûts de fonctionnement.
Trouver plus facilement des
professionnels de Hadoop

Idéal pour le traitement par lots.


Utilise MapReduce pour diviser convient pour l'analyse de données itérativeet en
Traitement
un grand ensemble de données sur direct. fonctionne avec les RDD et les DAG pour
des données
un cluster pour une analyse exécuter des opérations.
parallèle

Suit le processus de création de bloc RDD, puis il


Un système hautement tolérantaux
peut reconstruire un ensemble de données
Tolérance aux pannes.
lorsqu'une partition échoue. Sparkpeut également
pannes copie les données sur les nœudset
utiliser un DAG pour reconstruire les données sur
les utilise en cas de problème.
les nœuds.
Facilement scalable en ajoutantdes
nœuds et des disques pour le Un peu plus difficile à mettre à l'échelle car il
scalabilité stockage. Prend en charge des repose sur la RAM pour les calculs. Prend en
dizaines de milliers de nœuds sans charge des milliers de nœuds dans un cluster.
limite connue.

Non sécurisé. Par défaut, la sécurité est


Extrêmement sécurisé. Prend en
désactivée. Spark s'appuie sur l'intégrationavec
Sécurité charge LDAP, ACL, Kerberos, SLA,
Hadoop pour atteindre le niveau de sécurité
etc.
nécessaire.

Facilité Plus difficile à utiliser avec peude


Plus convivial. Permet le mode shell interactif. Les
d'utilisationet langages supportés. Utilise Java ou
API peuvent être écrites en Java, Scala, R, Python,
langages Python pour les applications
Spark SQL.
supporté MapReduce

plus lent que Spark. Les fragments


Machine de données peuvent être trop Beaucoup plus rapide avec le traitement en
Learning volumineux et créer desgoulots mémoire. Utilise MLlib pour les calculs.
d'étranglement.

Catégorie de
comparaison Hadoop Spark
Hadoop Spark

Utilise des solutions externes.


Planification YARN est l'option la plus courante
Dispose d'outils intégrés pour l'allocation, la
et gestion des pour la gestion des ressources.
planification et la surveillance des ressources.
ressources Oozie est disponible pour la
planification des flux de travail

1.5.1 Performance

En accédant aux données stockées localement sur HDFS, Hadoop améliore les performances globales. Cependant,
cela ne correspond pas au traitement en mémoire de Spark. Selon les affirmations d'Apache,Spark semble être 100
fois plus rapide lors de l'utilisation de la RAM pour le calcul que Hadoop avec MapReduce.

La domination est de même avec le tri des données sur des disques. Spark était 3 fois plus rapide et nécessitait 10 fois
moins de nœuds pour traiter 100 To de données sur HDFS. Cette référence a été suffisantepour établir le record du
monde en 2014.

La principale raison de cette suprématie de Spark est qu'il ne lit pas et n'écrit pas de données intermédiaires sur les
disques mais utilise de la RAM. Hadoop stocke les données sur de nombreuses
sources différentes, puis traite les données par lots à l'aide de MapReduce.

Tout ce qui précède peut positionner Spark comme le gagnant absolu. Cependant, si la taille des données est
supérieure à la RAM disponible, Hadoop est le choix le plus logique. Un autre point à prendre en compteest le coût de
fonctionnement de ces systèmes.

1.5.2 coût

En comparant Hadoop à Spark en terme de coût, nous devons creuser plus loin que le prix du logiciel. Lesdeux plates-
formes sont open source et entièrement gratuites.

Néanmoins, les coûts d'infrastructure, de maintenance et de développement doivent être pris en comptepour obtenir un
coût total de possession (TCO) approximatif.

Le facteur le plus important dans la catégorie des coûts est le matériel sous-jacent dont vous avez besoin pour
exécuter ces outils. Étant donné que Hadoop s'appuie sur n'importe quel type de stockage sur disque pour le traitement
des données, le coût de son fonctionnement est relativement faible.

D'autre part, Spark dépend des calculs en mémoire pour le traitement des données en temps réel. Ainsi,faire tourner des
nœuds avec beaucoup de RAM augmente considérablement le coût de possession.

Une autre préoccupation est le développement d'applications. Hadoop existe depuis plus longtemps queSpark et il est
moins difficile de trouver des développeurs de logiciels.

Les points ci-dessus suggèrent que l'infrastructure Hadoop est plus rentable. Bien que cette affirmation soitcorrecte, nous
devons nous rappeler que Spark traite les données beaucoup plus rapidement. Par conséquent, il faut un plus petit
nombre de machines pour effectuer la même tâche.

1.5.3 Traitement des données

Les deux frameworks traitent les données de manière assez différente. Bien que Hadoop avec MapReduce etSpark avec
RDD traitent les données dans un environnement distribué, Hadoop est plus adapté au traitement par lots. En revanche,
Spark brille par son traitement en temps réel.

L'objectif de Hadoop est de stocker des données sur des disques, puis de les analyser en parallèle par lots dans un
environnement distribué. MapReduce ne nécessite pas une grande quantité de RAM pour gérer degros volumes de
données. Hadoop s'appuie sur du matériel de tous les jours pour le stockage et convient mieux au traitement linéaire
des données.

Apache Spark fonctionne avec des ensembles de données distribués résilients (RDD). Un RDD est un ensemble
distribué d'éléments stockés dans des partitions sur des nœuds du cluster. La taille d'un RDD est généralement trop
grande pour être gérée par un nœud. Par conséquent, Spark partitionne les RDD sur les nœuds les plus proches et
effectue les opérations en parallèle. Le système suit toutes les actions effectuéessur un RDD à l'aide d'un graphe
acyclique dirigé (DAG).

Grâce aux calculs en mémoire et aux API de haut niveau, Spark gère efficacement les flux en direct de données
non structurées. De plus, les données sont stockées dans un nombre prédéfini de partitions. Un nœud peut avoir
autant de partitions que nécessaire, mais une partition ne peut pas s'étendre à un autrenœud.
1.5.4 Tolérance aux pannes

En parlant de Hadoop contre Spark dans la catégorie de tolérance aux pannes, nous pouvons dire que les deux offrent
un niveau suffisant de gestion des échecs. De plus, nous pouvons dire que leur approche de latolérance aux pannes est
différente.

Hadoop a la tolérance aux pannes comme base de son fonctionnement. Il réplique les données plusieursfois sur les
nœuds. En cas de problème, le système reprend le travail en créant les blocs manquants à partird'autres emplacements.
Les nœuds maîtres suivent l'état de tous les nœuds esclaves. Enfin, si un nœud esclave ne répond pas aux pings d'un
maître, le maître affecte les travaux en attente à un autre nœud esclave.

Spark utilise des blocs RDD pour atteindre la tolérance aux pannes. Le système suit la façon dont l'ensemblede données
immuable est créé. Ensuite, il peut redémarrer le processus en cas de problème. Spark peut reconstruire les données
dans un cluster en utilisant le suivi DAG des workflows. Cette structure de données permet à Spark de gérer les pannes
dans un écosystème de traitement de données distribué

1.5.5 Scalabilité

La frontière entre Hadoop et Spark devient floue dans cette section. Hadoop utilise HDFS pour gérer le BigData.
Lorsque le volume de données augmente rapidement, Hadoop peut rapidement évoluer pour répondre à la demande.
Étant donné que Spark n'a pas son système de fichiers, il doit s'appuyer sur HDFSlorsque les données sont trop
volumineuses pour être gérées.

Les clusters peuvent facilement s'étendre et augmenter la puissance de calcul en ajoutant plus de serveursau réseau. En
conséquence, le nombre de nœuds dans les deux frameworks peut atteindre des milliers. Il n'y a pas de limite ferme au
nombre de serveurs que vous pouvez ajouter à chaque cluster et à la quantité de données que vous pouvez traiter.

Certains des chiffres confirmés comportent 8 000 machines dans un environnement Spark avec des pétaoctets de
données. Quand on parle de clusters Hadoop, ils sont bien connus pour héberger des dizainesde milliers de machines et
près d'un exaoctet de données.

1.5.6 Facilité d'utilisation

Spark est peut-être le cadre le plus récent avec moins d'experts disponibles que Hadoop, mais il est connupour être plus
convivial. En revanche, Spark prend en charge plusieurs langages en plus du langage natif (Scala) : Java, Python, R et
Spark SQL. Cela permet aux développeurs d'utiliser le langage de programmation qu'ils préfèrent.

Le framework Hadoop est basé sur Java. Les deux langages principaux pour écrire du code MapReduce sont Java ou
Python. Hadoop n'a pas de mode interactif pour aider les utilisateurs. Cependant, il s'intègre aux outils Pig et Hive
pour faciliter l'écriture de programmes MapReduce complexes.

En plus de la prise en charge des API dans plusieurs langues, Spark gagne avec son mode interactif. Vouspouvez
utiliser le shell Spark pour analyser les données de manière interactive avec Scala ou Python. Le shell fournit un
retour instantané aux requêtes, ce qui rend Spark plus facile à utiliser que Hadoop MapReduce.
1.5.7 Machine Learning

L'apprentissage automatique est un processus itératif qui fonctionne mieux en utilisant le calcul enmémoire. Pour cette
raison, Spark s'est avéré être une solution plus rapide dans ce domaine.

La raison en est que Hadoop MapReduce divise les travaux en tâches parallèles qui peuvent être trop volumineuses pour
les algorithmes d'apprentissage automatique. Ce processus crée des problèmes deperformances d'I/O dans ces
applications Hadoop.

La bibliothèque Mahout est la principale plate-forme d'apprentissage automatique des clusters Hadoop. Mahout
s'appuie sur MapReduce pour effectuer le regroupement, la classification et la recommandation. Samsara a
commencé à remplacer ce projet.

Spark est livré avec une bibliothèque d'apprentissage automatique par défaut, MLlib. Cette bibliothèque effectue des
calculs ML itératifs en mémoire. Il comprend des outils pour effectuer la régression, la classification, la persistance, la
construction de pipelines, l'évaluation et bien d'autres.

Spark avec MLlib s'est avéré neuf fois plus rapide qu'Apache Mahout dans un environnement basé sur disque Hadoop.
Lorsque vous avez besoin de résultats plus efficaces que ce qu'offre Hadoop, Spark est lemeilleur choix pour
l'apprentissage automatique.

1.6 Idées fausses sur Hadoop et Spark

1.6.1 Idées fausses sur Hadoop

Hadoop est bon marché : Bien qu'il soit open source et facile à configurer, le fonctionnement continu du serveur peut être
coûteux.
Hadoop est une base de données : Bien que Hadoop soit utilisé pour stocker, gérer et analyser des données distribuées,
aucune requête n'est impliquée lors de l'extraction des données. Cela fait de Hadoopun entrepôt de données plutôt
qu'une base de données.
Hadoop n'aide pas les PME : Le « Big data » n'est pas réservé aux « grandes entreprises ». Hadoop a des
fonctionnalités simples comme les rapports Excel qui permettent aux petites entreprises d'exploiter sa puissance.
Avoir un ou deux clusters Hadoop peut grandement améliorer les performances d'une petite entreprise.
Hadoop est difficile à configurer : Bien que la gestion de Hadoop soit difficile aux niveaux supérieurs, ilexiste de
nombreuses interfaces utilisateur graphiques (GUI) qui simplifient la programmation pour MapReduce.

1.6.2 Idées fausses courantes sur Spark

Spark est une technologie en mémoire : Bien que Spark utilise efficacement l'algorithme le moins récemment
utilisé (LRU), il ne s'agit pas en soi d'une technologie basée sur la mémoire.
Spark fonctionne toujours 100 fois plus vite que Hadoop : Bien que Spark puisse fonctionner jusqu'à 100 fois plus vite que
Hadoop pour les petites charges de travail, selon Apache, il ne fonctionne généralement que jusqu'à 3 fois plus vite
pour les grandes.
Spark introduit de nouvelles technologies dans le traitement des données : Bien que Spark utilise efficacement
l'algorithme LRU et le traitement des données par pipeline, ces fonctionnalités existaient
auparavant dans les bases de données de traitement massivement parallèle (MPP). Cependant, ce quidistingue Spark de
MPP est son orientation open source.

1.7 Cas d'utilisation Hadoop et Spark

En examinant Hadoop par rapport à Spark dans les sections ci-dessus, nous pouvons extraire quelques casd'utilisation
pour chaque framework.

1.7.1 Cas d'utilisation Hadoop

Hadoop est plus efficace pour les scénarios impliquant les éléments suivants :

Traitement d'ensembles de données volumineux dans des environnements où la taille des donnéesdépasse la
mémoire disponible
Traitement par lots avec des tâches qui exploitent les opérations de lecture et d'écriture sur disqueConstruire une
infrastructure d'analyse de données avec un budget limité
Terminer des travaux qui ne sont pas urgents

Analyse des données historiques et d'archives

1.7.2 Cas d'utilisation Spark

Spark est plus efficace pour les scénarios impliquant les éléments suivants :

Traiter des chaînes d'opérations parallèles en utilisant des algorithmes itératifs


Obtenir des résultats rapides avec des calculs en mémoireAnalyser
l'analyse des données de flux en temps réel Traitement graphique
parallèle pour modéliser les donnéesToutes les applications de ML

1.8 Hadoop ou Spark ?

Hadoop et Spark sont des technologies de traitement du Big Data. En dehors de cela, ce sont des cadresassez différents
dans la façon dont ils gèrent et traitent les données.

Selon les sections précédentes, il semble que Spark soit le grand gagnant. Bien que cela puisse être vrai dans une
certaine mesure, en réalité, ils ne sont pas créés pour se faire concurrence, mais plutôt pour secompléter.
Bien sûr, comme nous l'avons indiqué plus haut dans cet article, il existe des cas d'utilisation où l'un ou l'autre
framework est un choix plus logique. Dans la plupart des autres applications, Hadoop et Spark fonctionnent mieux
ensemble. En tant que successeur, Spark n'est pas là pour remplacer Hadoop mais pourutiliser ses fonctionnalités pour
créer un nouvel écosystème amélioré.

En combinant les deux, Spark peut tirer parti des fonctionnalités qui lui manquent, comme un système de fichiers.
Hadoop stocke une énorme quantité de données à l'aide de matériel abordable et effectue ensuite des analyses, tandis
que Spark apporte un traitement en temps réel pour gérer les données entrantes. Sans Hadoop, les applications métier
peuvent manquer des données historiques cruciales que Spark ne gère pas.

Dans cet environnement coopératif, Spark tire également parti des avantages de Hadoop en matière desécurité et de
gestion des ressources. Avec YARN, le clustering Spark et la gestion des données sontbeaucoup plus faciles. Vous
pouvez exécuter automatiquement des charges de travail Spark à l'aide de toutes les ressources disponibles.

Cette collaboration fournit les meilleurs résultats en matière d'analyse rétroactive des données transactionnelles,
d'analyse avancée et de traitement des données IoT. Tous ces cas d'utilisation sontpossibles dans un environnement.

Les créateurs de Hadoop et Spark avaient l'intention de rendre les deux plates-formes compatibles et deproduire des
résultats optimaux adaptés à toutes les exigences de l'entreprise.
2 Utiliser Spark

2.1 Preparation de l'environnement

1. Spark

Télécharger la version 3.0.3 de Spark compatible avec Hadoop 2.7

https://www.apache.org/dyn/closer.lua/spark/spark-3.0.3/spark-3.0.3-bin-hadoop2.7.tgz

https://dlcdn.apache.org/spark/spark-3.0.3/spark-3.0.3-bin-hadoop2.7.tgz

Puis extraire le répertoire et le placer quelque part. Ex: C:\BigDataSoft\spark-3.0.3-bin-hadoop2.7

2. Hadoop: Vous

pouvez :

extraire le fichier zip fourni avec le cours et le placer quelque part. Ex : C:\BigDataSoft\winutils-
master\hadoop-2.7.1. I

PS: Ici on a juste une petite dépendance à régler sur Windows. Dans le cadre de ce cours, on ne ferapas en mode
HADOOP + SPARK sur votre PC personnel. Le mode du déploiement StandAlone de SPARK ne dépend pas
de Hadoop. Donc théoriquement, nous n'avons pas besoin de HADOOP. En revanche, spark est fait pour être
utilisé sur des servers de Linux. Afin de faire fonctionner Spark surWindows, il nous faut donc ce petit
plugin de Hadoop dédié au OS Windows. Pour les élèves motivés, si vous voulez essayer HADOOP +
SPARK, vous pouvez télécharger une distribution complète sur le site
https://archive.apache.org/dist/hadoop/common . La version 2.7.X est recommendée

3. Java:

Vous pouvez

soit utiliser le installer fourni avec le cours jdk-8u202-windows-x64.exe

soit aller sur le site d'Oracle https://www.oracle.com/java/technologies/javase/javase8-archive-


downloads.html pour télécharger JAVA. La version 8 est recommendée

3. Configurer vos variables du système(cf Installation de Mongo)


4. Ainsi la variable PATH

Lorsque tous les étapes sont terminées, tapezque spark-shell dans un environnement shell et vous verrez
Spark aura bien démarré.
C'est donc l'environnement interactif de Spark. Par défaut, le langage utilisé est en Scala.

Vous pouvez ensuite tapez la commande pyspark . Nous avons donc maintenant un environnement de
Spark en Python, dans lequel vous pouvez écrire du code Python. Mais comme on utilise un interpreteur du Python
dans Anaconda, ce mode d'emploi n'est pas bien configuré, donc non recommandée dans le cadre de ce cours. Et on
verra comment écrire du progamme Spark en Python dans Anaconda.

Gardez l'environnement du shell, dans un Web browser ouvrir la page http://localhost:4040/ . C'est donc unmoniteur
du cluster de Spark, bien qu'on n'ait qu'un seul Executor(équivalent au worker/slave) dans ce cluster qui est aussi son
propre Driver (équivalent au master)
2.2 Soumettre une tâche au cluster Spark en mode Local

Dans le dossier spark-3.0.3-bin-hadoop2.7\examples\src\main\python , on retrouve des


exemples du Spark écrits en Python. On verra dans cette section comment exécuter ces programmes enPython.

On fait appel ici à une commande qui s'appelle spark-submit . Rapplons nous que le dossier spark-
3.0.3-bin-hadoop2.7\bin est ajouté dans le PATH du système par une concaténation de
%SPARK_HOME%\bin. En fait dans ce dossier, il y a un tas de commande de Spark, y compris spark-
shell, pyspark et spark-submit
Exécutons donc la commande suivant dans un shell (Attention! on n'est plus dans le mode interactif deSpark) en
utilisant votre chemin du fichier pi.py.

spark-submit --master local[*] /votre/chemin/du/fichier/pi.py 10

Par exemple:

spark-submit --master local[*] C:\BigDataSoft\spark-3.0.3-bin-


hadoop2.7\examples\src\main\python\pi.py 10

10 étant le paramètre demandé par le programme pi.py, il signifie le nb d'itération.

Après environ 7.7 s, la valeur de Pi est estimé à 3.139 (Cette valeur est aléatoire, elle différente de chaqueexécution)

Le temps peut apparaître long pour faire ce petit calcul. Mais vous devez savoir que ce temps comporte letemps de
démarrage du server.

Voici le programme pi.py. Vous arrivez à le comprendre après l'étude des prochains chapitres.
2.3 Démarrage un cluster en mode StandAlone

Linux/mac OS

Vous pouvez démarrer un serveur maître autonome en exécutant :

./sbin/start-master.sh

Une fois démarré, le maître imprimera une URL spark://HOST:PORT pour lui-même, que vous pouvez utiliser pour y
connecter les Workers, ou passer comme argument "maître" à SparkContext. Vous pouvez également trouver cette URL
sur l'interface utilisateur Web du maître, qui est http://localhost:8080 par défaut.

De même, vous pouvez démarrer un ou plusieurs workers et les connecter au master via :

./sbin/start-worker.sh <master-spark-URL>

Une fois que vous avez démarré un worker, regardez l'interface utilisateur Web du maître. Vous devriez voirle nouveau
nœud répertorié ici, ainsi que son nombre de processeurs et de mémoire (moins un gigaoctet restant pour le système
d'exploitation).

Windows:

Utilisons Powershell par exemple :

Vous pouvez démarrer un serveur maître


spark-class org.apache.spark.deploy.master.Master

Récupérons ensuite le URL Spark du server maître, qui est spark://172.17.64.1:7077.

Pour démarrer un serveur Worker, exécuter la commande suivante dans n'importe quelle machine dans leréseau
cluster. Ici on utilisera la même machine.

spark-class org.apache.spark.deploy.worker.Worker spark://ip:port

Dans un nouveau Powershell, saisissez la commande ci-dessus avec le url du master

Dans le moniteur de Master http://localhost:8080/ , on peut voir qu'un noeud Worker est effectivementajouté dans
le cluster.
2.4 Soumettre une tâche au cluster Spark en mode StandAlone

Nous avons vu préalablement comment soumettre la tâche du calcul de Pi en mode local. De même, nous pouvons
soumettre cette tâche dans un cluster en mode StandAlone. La seule différence est donc la valeur du paramètre --
master.

spark-submit --master spark://ip:port /votre/chemin/du/fichier/pi.py 10

Avec la commande suivante

spark-submit --master spark://172.17.64.1:7077 C:\BigDataSoft\spark-3.0.3-bin-


hadoop2.7\examples\src\main\python\pi.py 100

nous avons donc effectué un calcul avec 100 itération au bout de 85s. La valeur de Pi estimé est donc 3.1408

Nous pouvons confirmer à travers le moniteur que cette tâche est bien ajouté dans notre cluster StandAlonedémarré
dans la section précédente.

en cours d'exécution
fin d'exécution

2.5 Installation de Pyspark dans Anaconda

L'installation de PySpark à l'aide de PyPI est la suivante :

pip install pyspark

1. Ouvrir le terminal dans Anaconda


2. Saisir "pip installer pyspark"

3. Installer également la bibliothèque

pip install findspark

2.6 Premier exemple "WordCount"

Préparez d'abord un fichier txt comme celui pour le MapReduce. J'ai saisi le contenu suivant pour
l'illustration et sauvegarder ce fichier sur le chemin C:\BigDataSoft\Input\words.txt

Hello Python
Hello Hadoop
Hello Spark
Spark SQL
Spark Streaming
Spark Flink
Spark Python
Spark Scala

Comme nous avons actuellement 2 copies de Pyspark(une dans la distribution complète de Spark que nous avons
téléchargée manuellement, l'autre dans l'environnement d'Anaconda que nous venons de téléchargerpar la commande),
nous utilisons le code suivant pour informer notre interprêteur Python quel spark il doit démarrer. Normalement si
vous avez bien configurer les variables d'environnement avec la bonne version de spark, on ne doit pas avoir du
soucis sur Windows. Il y a actuellement une petite incompatibilité de la version 3.2 avec Windows.
import findspark
findspark.init("C:\BigDataSoft\spark-3.0.3-bin-hadoop2.7")
from pyspark import SparkConf,SparkContext

# create Spark context with necessary configuration


conf = SparkConf().setMaster("local").setAppName("Demo")
sc = SparkContext(conf=conf)

la variable context sc est extrêmement importante dans la programmation en Spark. Elle est crée et
retenue automatique dans un environnement interactif Shell de Spark.

# read data from text file and split each line into words
file_rdd = sc.textFile("C:\\BigDataSoft\\Input\\Words.txt")
words_rdd = file_rdd.flatMap(lambda line: line.split(" "))

# count the occurrence of each word


words_tuple_rdd = words_rdd.map(lambda x:(x,1))
result_rdd = words_tuple_rdd.reduceByKey(lambda a,b: a+b)

print(result_rdd.collect())

Exercice:

1. Exécutez cet exemple dans un shell interactif de Spark


2. Soumettre cet exemple via spark-submit dans les deux modes local et StandAlone.
3 Resilient Distributed Dataset(RDD)

À un niveau élevé, chaque application Spark se compose d'un programme pilote(Driver) qui exécute la fonction
principale de l'utilisateur et exécute diverses opérations parallèles sur un cluster. La principale abstraction fournie
par Spark est un jeu de données distribué résilient (RDD), qui est une collection d'éléments partitionnés sur les
nœuds du cluster qui peuvent être exploités en parallèle. Les RDD sont créésen commençant par un fichier dans le
système de fichiers Hadoop (ou tout autre système de fichiers pris encharge par Hadoop), ou une collection Scala
existante dans le programme du pilote, et en le transformant. Les utilisateurs peuvent également demander à Spark de
conserver un RDD en mémoire, ce qui lui permet d'être réutilisé efficacement dans des opérations parallèles. Enfin,
les RDD récupèrent automatiquement après les pannes de nœud.

3.1 Caractéristiques de Resilient Distributed Dataset (RDD)

Évaluation paresseuse (Lazy Evaluation)


Toutes les transformations d'Apache Spark sont paresseuses, ce qui signifie qu'elles ne calculent pas lesrésultats
comme et lorsqu'ils sont indiqués dans les instructions de transformation. Au lieu de cela, ils gardent une trace des
tâches de transformation en utilisant le concept de DAG (Directed Acyclic Graphs).Spark calcule ces transformations
lorsqu'une action nécessite un résultat pour le programme pilote.

Calcul en mémoire
Spark utilise le calcul en mémoire pour accélérer le temps de traitement total. Dans le calcul en mémoire, les données
sont conservées dans la RAM (mémoire à accès aléatoire) au lieu des lecteurs de disque plus lents. Ceci est très utile
car il réduit le coût de la mémoire et permet la détection de modèles, analyse les données volumineuses plus
efficacement. Les principales méthodes qui l'accompagnent sont les méthodes

cache() et persist().

Tolérance aux pannes


Les RDD sont tolérants aux pannes car ils peuvent suivre les informations de lignage des données pour permettre la
reconstruction automatique des données perdues en cas de panne. Pour obtenir une toléranceaux pannes pour les RDD
générés, les données obtenues sont répliquées entre divers exécuteurs Spark dansles nœuds de travail du cluster.

Immutabilité
Comme il est facile de partager les données immuables en toute sécurité entre plusieurs processus, cela s'avère être
une option très valable. L'immuabilité exclut simplement de nombreux problèmes potentielsdus à diverses mises à
jour à partir de différents threads à la fois. Il est plus sûr de partager des données immuables entre les processus. Mais,
les RDD ne sont pas seulement des fonctions immuables, mais aussi des fonctions déterministes de leurs entrées, ce
qui permet de recréer les parties RDD à n'importe quel moment donné. Nous pouvons considérer les RDD non
seulement comme une collection de données, maiscomme une recette pour créer de nouvelles données à partir
d'autres données.
Partitionnement
Les RDD sont généralement des collections de divers éléments de données de volumes massifs, qui ne peuvent
pas tenir dans un seul nœud et doivent être partitionnés sur plusieurs nœuds. Spark effectue automatiquement ce
partitionnement des RDD et distribue ces partitions sur différents nœuds. Les pointsclés liés à ces partitions sont

Chaque nœud d'un cluster Spark contient une ou plusieurs partitions.Les


partitions dans ne s'étendent pas sur plusieurs machines.
Le nombre de barrières dans Spark est configurable et doit être choisi de manière efficace.

En augmentant le nombre d'exécuteurs sur le cluster, le parallélisme peut être augmenté dans lesystème.

Capacité de configuration de l'emplacement


Les RDD sont capables d'une préférence de placement claire pour calculer les partitions. La préférence deplacement
fait référence aux informations définissant l'emplacement de RDD. Ici, le DAG entre en jeu et place les partitions de
manière à ce que la tâche soit proche des données dont elle a besoin. Par conséquent, la vitesse de calcul est
augmentée

3.2 Comparaison : RDD vs Dataset vs DataFrame

3.2.1 RDD

Un RDD ou Resilient Distributed Dataset est la structure de données fondamentale réelle d'Apache Spark. Cesont des
collections immuables (en lecture seule) d'objets de différents types, qui calculent sur les différents nœuds d'un
cluster donné. Ceux-ci fournissent la fonctionnalité permettant d'effectuer des calculsen mémoire sur de grands clusters
de manière tolérante aux pannes. Chaque ensemble de données dans le RDD Spark est bien partitionné sur de nombreux
serveurs afin qu'ils puissent être calculés efficacement sur différents nœuds du cluster.

3.2.2 DataSet

Dans Apache Spark, l'ensemble de données est une structure de données dans Spark SQL qui est fortementtypée,
orientée objet et est une carte vers un schéma relationnel. Il représente une requête structurée avec des encodeurs et est
une extension de l'API Data-frame. Ceux-ci sont à la fois sérialisables et interrogeables,donc persistants par nature. Il
fournit une interface unique pour les langages Scala et Java. Cela réduit également la charge des bibliothèques.

3.2.3 DataFrame

On peut dire que les Data-Frames sont des Dataset organisés en colonnes nommées. Celles-ci sont très similaires à
la table d'une base de données relationnelle. L'idéologie est de permettre le traitement d'une grande quantité de
données structurées. Data-Frame contient des lignes avec un schéma où le schéma estl'illustration de la structure des
données. Il fournit une gestion de la mémoire et des plans d'exécution optimisés.
3.3 Création d'un RDD


Rappel:

la manipulation de RDD dépend de la variable context

conf = SparkConf().setMaster("local").setAppName("Demo") sc = SparkContext(conf=conf)

Ensemble de données distribué résilient (Resilient Distributed Dataset, RDD), qui est une collection d'éléments
tolérants aux pannes qui peuvent être utilisés en parallèle. Il existe trois façons de créer des RDD
: paralléliser une collection existante dans votre programme de pilote ou référencer un ensemble de données dans un
système de stockage externe, tel qu'un système de fichiers partagé, HDFS, HBase ou toutesource de données offrant un
Hadoop InputFormat, et créer un RDD à partir d'un RDD existant

3.3.1 Paralléliser une collection

Les collections parallélisées sont créées en appelant la méthode parallelize de SparkContext sur un
itérable ou une collection existante dans votre programme de pilote. Les éléments de la collection sontcopiés
pour former un jeu de données distribué qui peut être exploité en parallèle. Par exemple, voici comment créer une
collection parallélisée contenant les nombres 1 à 5 :

data = [1, 2, 3, 4, 5]
distData = sc.parallelize(data)

3.3.2 Référencer un jeu de données externe

Les RDD de fichiers texte peuvent être créés à l'aide de la méthode textFile de SparkContext. Cette
méthode prend un URI pour le fichier (soit un chemin local sur la machine, soit un URI hdfs://, s3a://, etc.) etle lit
comme une collection de lignes. Voici un exemple d'invocation :

distFile = sc.textFile("data.txt")

Quelques notes sur la lecture de fichiers avec Spark :

Si vous utilisez un chemin sur le système de fichiers local, le fichier doit également être accessible aumême chemin
sur les noeuds worker. Copiez le fichier sur tous les nœuds de calcul ou utilisez un système de fichiers partagé
monté sur le réseau.
Toutes les méthodes d'entrée basées sur des fichiers de Spark, y compris textFile, prennent égalementen charge
l'exécution sur des répertoires, des fichiers compressés et des caractères génériques. Par exemple, vous pouvez
utiliser textFile("/my/directory"), textFile("/my/directory/ .txt") et textFile("/my/directory/ .gz").
La méthode textFile prend également un deuxième argument facultatif pour contrôler le nombre de partitions du
fichier. Par défaut, Spark crée une partition pour chaque bloc du fichier (les blocs étant de 128 Mo par défaut
dans HDFS), mais vous pouvez également demander un nombre de partitions plus élevé en passant une valeur
plus grande. Notez que vous ne pouvez pas avoir moins de partitionsque de blocs.

3.3.3 Créer un RDD à partir d'un RDD existant

La transformation transforme un RDD en un autre, et le changement est le moyen de créer un RDD à partir d'un RDD
existant. Cela crée une différence entre Apache Spark et Hadoop MapReduce. La conversion fonctionne comme celle
qui absorbe un RDD et en produit un. Le RDD d'entrée ne change pas et, comme lesRDD sont immuables, il génère des
RDD variables en appliquant des opérations.

Il existe deux opérations de transformations et d'actions Apache Spark RDD. Une transformation est une fonction qui
produit un nouveau RDD à partir des RDD existants. Il prend un RDD en entrée et génère un ouplusieurs RDD en
sortie. Chaque fois qu'il crée un nouveau RDD lorsque nous appliquons une transformation. Ainsi, tous les RDD
d'entrée ne peuvent pas être modifiés car les RDD sont immuables.

Aucune modification du cluster.

Produit un DAG qui garde une trace de quel RDD a été créé lors du cycle de vie.Exemple :

map(func), filter(func), Reduce(func), intersection(dataset),

distinct(), groupByKey(), union(dataset), mapPartitions(fun), flatMap().

3.4 Opérateur Transformation vs Action

3.4.1 Types de Transformation

Transformations étroites : dans ce type, tous les éléments nécessaires pour calculer les enregistrementsd'une seule
partition résident dans cette seule partition. Ici, nous utilisons un sous-ensemble limité departition pour calculer
le résultat. Les transformations étroites sont le résultat de map(), filter().
Transformations étendues : ici, tous les éléments requis pour calculer les enregistrements dans cettepartition
unique peuvent résider dans de nombreuses partitions du RDD parent. Ceux-ci utilisent
groupbyKey() et reducebyKey().
3.4.2 Actions

Les transformations dans Apache Spark créent des RDD les unes des autres, mais pour travailler sur unensemble
de données réel, puis nous effectuons des opérations d'action. Ici, le nouveau RDD n'est pasformé mais donne des
valeurs non-RDD en tant que résultats qui sont stockés sur les pilotes ou sur le système de stockage externe. Cela
apporte de la paresse au traitement des RDD.
Les actions sont un moyen d'envoyer des données de l'exécuteur au pilote où les exécuteurs sont responsables de
l'exécution d'une tâche. Dans le même temps, le pilote est un processus JVM qui gère lestravailleurs et l'exécution de
la tâche.

Quelques exemples incluent : count(), collect(), take(n), top(), count value(),


reduce(), fold(),aggregate(), foreach().
3.4.3 les APIs
3.4.3.1 map( func )

Renvoie un nouveau RDD en appliquant une fonction à chaque élément de ce RDD.

rdd = sc.parallelize(["b", "a", "c"])


rdd2 = rdd.map(lambda x: (x, 1))
print(rdd2.collect())

3.4.3.2 flatMap( func )

Renvoie un nouveau RDD en appliquant d'abord une fonction à tous les éléments de ce RDD, puis en
aplatissant les résultats.

rdd = sc.parallelize(["hadoop spark hadoop", "Hello Python", "spark flink


hadoop"])
rdd2 = rdd.map(lambda line: line.split(" "))
print(rdd2.collect())
rdd3 = rdd.flatMap(lambda line: line.split(" "))
print(rdd3.collect())

3.4.3.3 filter( func )

Renvoie un nouvel ensemble de données formé en sélectionnant les éléments de la source sur lesquels funcrenvoie true.

rdd = sc.parallelize([1, 2, 3, 4, 5])


rdd2 = rdd.filter(lambda x: x % 2 == 0)
print(rdd2.collect())
3.4.3.4 groupBy( func )

Renvoie un RDD d'éléments groupés par la valeur de la fonction en paramètre.

rdd = sc.parallelize([1, 1, 2, 3, 5, 8])


result = rdd.groupBy(lambda x: x % 2).collect()
print(result)
print([(x, sorted(y)) for (x, y) in result])

3.4.3.5 sortBy( func )

Trie ce RDD par la la valeur de la fonction donnée en paramètre

tmp = [('a', 1), ('b', 2), ('1', 3), ('d', 4), ('2', 5)]
print(sc.parallelize(tmp).sortBy(lambda x: x[0]).collect())

print(sc.parallelize(tmp).sortBy(lambda x: x[1]).collect())

3.4.3.6 groupByKey()

Lorsqu'il est appelé sur un ensemble de données de paires (K, V), renvoie un ensemble de données depaires (K,
Iterable).

Remarque : Si vous effectuez un regroupement afin d'effectuer une agrégation (telle qu'une somme ou une
moyenne) sur chaque clé, l'utilisation de reduceByKey ou d' aggreggateByKey donnera de bien
meilleures performances.
rdd = sc.parallelize([('a', 1), ('a', 2), ('b', 1), ('b', 1), ('b', 1)])
result = rdd.groupByKey()
print(result)
print(result.map(lambda t:(t[0], list(t[1]))).collect())

3.4.3.7 reduceByKey( func )

Lorsqu'il est appelé sur un ensemble de données de paires (K, V), renvoie un ensemble de données de paires (K, V)
où les valeurs de chaque clé sont agrégées à l'aide de la fonction de réduction donnée func, quidoit être de type (V, V)
=> V

rdd = sc.parallelize([('a', 1), ('a', 2), ('b', 1), ('b', 1), ('b', 1)])
result = rdd.reduceByKey(lambda a, b: a + b ).collect()
print(result)

3.4.3.8 sortByKey()

Lorsqu'il est appelé sur un ensemble de données de paires (K, V) où K implémente Ordered, renvoie un ensemble
de données de paires (K, V) triées par clés dans l'ordre croissant ou décroissant, comme spécifiédans l'argument
booléen croissant.

tmp = [('a', 1), ('b', 2), ('1', 3), ('d', 4), ('2', 5)]
print(sc.parallelize(tmp).sortByKey().first())
print(sc.parallelize(tmp).sortByKey(True).collect())
print(sc.parallelize(tmp).sortByKey(False).collect())
3.4.3.9 mapValues( func )

Transmet chaque valeur de la paire clé-valeur RDD via une fonction de mappage sans modifier les clés ; celaconserve
également le partitionnement du RDD d'origine.

rdd = sc.parallelize([('a', 1), ('a', 2), ('b', 1), ('b', 1), ('b', 1)])
print(rdd.mapValues(lambda x: x*10).collect())

3.4.3.10 distinct()

Renvoie un nouveau RDD contenant les éléments distincts de ce RDD.

rdd = sc.parallelize([1, 1, 2, 3])


print(rdd.distinct().collect())

3.4.3.11 union()

Renvoie l'union de ce RDD et d'un autre.

rdd = sc.parallelize([1, 1, 2, 3])


print(rdd.union(rdd).collect())
3.4.3.12 intersection()

Renvoie l'intersection de ce RDD et d'un autre. La sortie ne contiendra aucun élément en double, même siles RDD
d'entrée en contenaient.

rdd1 = sc.parallelize([1, 10, 2, 3, 4, 5])


rdd2 = sc.parallelize([1, 6, 2, 3, 7, 8])
print(rdd1.intersection(rdd2).collect())

3.4.3.13 join()

Lorsqu'il est appelé sur des ensembles de données de type (K, V) et (K, W), renvoie un ensemble de donnéesde paires
(K, (V, W)) avec toutes les paires d'éléments pour chaque clé.

Les jointures externes sont prises en charge via leftOuterJoin , rightOuterJoin et


fullOuterJoin .

x = sc.parallelize([("a", 1), ("b", 4)])


y = sc.parallelize([("a", 2), ("a", 3)])
print(x.join(y).collect())

3.4.3.14 glom()

Renvoie un RDD créé en fusionnant tous les éléments de chaque partition dans une liste.

rdd = sc.parallelize([1, 2, 3, 4, 5, 6, 7, 8, 9], 3)


print(rdd.glom().collect())
3.4.3.15 collect()

Renvoie tous les éléments de l'ensemble de données sous forme de tableau au niveau du programme pilote.

Attention: Ceci est généralement utile après un filtre ou une autre opération qui renvoie un sous-ensemble
suffisamment petit des données.

3.4.3.16 first()

Renvoie le premier élément de l'ensemble de données (similaire à take(1)).

sc.parallelize([2, 3, 4]).first()

3.4.3.17 count()

Renvoie le nombre d'éléments dans l'ensemble de données.

sc.parallelize([2, 3, 4]).count()

3.4.3.18 take( num )

Prend les premiers num éléments du RDD.

Attention: Cette méthode ne doit être utilisée que si le tableau résultant est censé être petit, car toutesles données sont
chargées dans la mémoire du pilote.

sc.parallelize([7,2, 3, 4, 5, 6]).take(2)

3.4.3.19 top( num )

Prend les num premiers éléments d'un RDD. Il renvoie la liste triée par ordre décroissant.

Attention: Cette méthode ne doit être utilisée que si le tableau résultant est censé être petit, car toutesles données sont
chargées dans la mémoire du pilote.

sc.parallelize([7,2, 3, 4, 5, 6]).top(2)
3.4.3.20 countByKey()

Compte le nombre d'éléments pour chaque clé et renvoyez le résultat au maître sous forme de dictionnaire.

rdd = sc.parallelize([("a", 1), ("b", 1), ("a", 1)])


print(rdd.countByKey())

3.4.3.21 reduce( func )

Agréger les éléments de l'ensemble de données à l'aide d'une fonction func (qui prend deux arguments et en renvoie
un). La fonction doit être commutative et associative pour pouvoir être calculée correctement enparallèle.

sc.parallelize([1, 2, 3, 4, 5]).reduce(lambda a,b: a+b)

3.4.3.22 takeSimple( withReplacement, num, seed=None )

Renvoie un sous-ensemble échantillonné de taille fixe de ce RDD.

rdd = sc.parallelize(range(0, 10))


print(rdd.takeSample(True, 20))
print(rdd.takeSample(False, 5))

3.4.3.23 takeOrdered( num** , key=None )

Prend les N éléments d'un RDD classés par ordre croissant ou comme spécifié par la fonction de clé
facultative.

print(sc.parallelize([10, 1, 2, 9, 3, 4, 5, 6, 7]).takeOrdered(3))

print(sc.parallelize([10, 1, 2, 9, 3, 4, 5, 6, 7], 2).takeOrdered(4, key=lambda x:


-x))

3.4.3.24 saveAsTextFile( path )

sc.parallelize(range(10)).saveAsTextFile("output1")
sc.parallelize(range(10), 3).saveAsTextFile("output2")

Observer le résultat et réfléchir à l'aide du dernier module


3.4.3.25 mapPartitions( func, preservesPartitioning=False )

Renvoie un nouveau RDD en appliquant une fonction à chaque partition de ce RDD.

Au lieu de travailler sur chaque élément dans une partition comme map() , mapPartitions travaille
sur toute la partition, donc en général plus performante que map.

rdd = sc.parallelize([1, 2, 3, 4], 2)


def process(iterables):
result = list()
for it in iterables:
result.append(it*10)
return result
print(rdd.mapPartitions(process).collect() )

3.4.4 Le flux de RDD dans l'architecture Spark

1. Spark crée un graphique lorsque vous entrez du code dans la console Sparking.
2. Lorsqu'une action est appelée sur Spark RDD, Spark soumet le graphique au planificateur DAG.
3. Les opérateurs sont divisés en étapes de tâches dans le planificateur DAG.
4. Les étapes sont transmises au planificateur de tâches, qui lance la tâche via le gestionnaire de cluster.

3.4.5 Cycle de vie d'un programme Spark

1. Créez des RDD d'entrée à partir de données externes ou parallélisez une collection dans votre
programme pilote.
2. Transformez-les paresseusement pour définir de nouveaux RDD à l'aide de transformations telles quefilter() ou
map()
3. Facultatif : demandez à Spark de mettre en cache() tous les RDD intermédiaires qui devront être réutilisé.
4. Lancer des actions telles que count() et collect() pour lancer un calcul parallèle,qui est
ensuite optimisé et exécuté par Spark.
3.5 Limitations du RDD dans Apache Spark

3.5.1 Pas d'optimisation automatique

Dans Apache Spark, le RDD n'a pas d'option pour l'optimisation automatique des entrées. Il est incapable d'utiliser les
optimiseurs avancés Spark tels que l'optimiseur Catalyst et le moteur d'exécution Tungsten, etnous ne pouvons donc
effectuer qu'une optimisation RDD manuelle. Ceci est surmonté dans les concepts Dataset et DataFrame, où les deux
utilisent le Catalyst pour générer un plan de requête logique et physiqueoptimisé. Il fournit de l'espace et de l'efficacité
de vitesse.

3.5.2 Pas de sécurité statique et de type Runtime

RDD ne fournit pas de sécurité statique ou de type Runtime et ne permet pas à l'utilisateur de vérifier leserreurs lors
de l'exécution. Mais, Dataset fournit une sécurité de type au moment de la compilation pourcréer des workflows de
données complexes. Cela facilite la détection des erreurs au moment de la compilation et rend ainsi le code plus
sûr.

3.5.3 Le problème du débordement

RDD se dégrade lorsqu'il n'y a pas assez de mémoire disponible pour le stocker en mémoire ou sur disque. Ici, les
partitions qui débordent de la RAM peuvent être stockées sur disque et offriront le même niveau de performances.
Nous devons augmenter la RAM et la taille du disque pour surmonter ce problème.
3.5.4 Surcharge de sérialisation et de récupération de place (limitation des
performances)

Comme RDD est un objet en mémoire, il implique la surcharge de Garbage Collection et de la sérialisation Java, qui
devient coûteuse avec la croissance des données. Pour surmonter cela, nous pouvons utiliser desstructures de données
avec moins d'objets à moindre coût ou conserver l'objet sous forme sérialisée.

3.5.5 Aucune vue schématique des données

RDD a un problème avec la gestion des données structurées. En effet, il ne fournit pas de vue schématique des données
et n'a aucune disposition dans ce contexte. Dataset et DataFrame fournissent une vue Schémaet sont une collection
distribuée de données organisées en colonnes nommées.
4 Pyspark SQL &DataFrame

Spark SQL est un module d'Apache Spark pour la gestion de données structurées. Avec Spark SQL, vous pouvez
traiter des données structurées en utilisant le type d'interface SQL. Ainsi, si vos données peuvent être représentées
sous forme de tableau ou se trouvent déjà dans les sources de données structurées tellesque la base de données SQL,
vous pouvez utiliser SparkSQL pour les traiter.

Spark SQL fournit une API appelée API dataframes qui permet de mélanger des requêtes SQL, des techniques de
manipulation de dataframe comme pandas et des transformations et actions habituelles d'unRDD. Il est donc très bien
intégré.

Une DataFrame est un ensemble de données organisé en colonnes nommées. Il est conceptuellement équivalent à
une table dans une base de données relationnelle ou à une trame de données dans R/Python,mais avec des
optimisations plus riches sous le capot. Les DataFrames peuvent être construits à partir d'unlarge éventail de sources
telles que : des fichiers de données structurés, des tables dans Hive, des bases dedonnées externes ou des RDD
existants. L'API DataFrame est disponible dans Scala, Java, Python et R. DansScala et Java, un DataFrame est
représenté par un ensemble de données de lignes

Que vos données soient en HDFS, Hive ou bases de données relationnelles et que vos données soient auformat
AVO, parquet, ORC ou JSON, vous pouvez accéder et traiter les données de manière uniforme.

Avec Spark SQL, vous pouvez exécuter vos requêtes Hive sans aucune modification. Et vous pouvez utiliservos outils
de BI existants pour interroger le Big Data.

De plus, vous pouvez même joindre des données dans différents formats et différentes sources de données.C'est ainsi

que Spark SQL fournit un accès uniforme aux données.

4.1 Point de départ : SparkSession

Comme pour RDD, nous avons besoin de sc , il est de même pour SparkSQL.

La SparkSession, introduite dans Spark 2.0, fournit un point d'entrée unifié pour la programmation de Sparkavec les
API structurées. Vous pouvez utiliser une SparkSession pour accéder à toutes les fonctionnalités de
Spark . Pour créer une SparkSession de base, utilisez simplement SparkSession.builder() :
from pyspark.sql import SparkSession

spark = SparkSession \
.builder \
.appName("Python Spark SQL basic example") \
.config("spark.some.config.option", "some-value") \
.getOrCreate()

Nous pouvons aussi obtenir Spark Context à partir de SparkSession

sc = spark.sparkContext

4.2 Créer des DataFrames

Un DataFrame PySpark peut être créé via pyspark.sql.SparkSession.createDataFrame généralement en passant une
liste de listes, tuples, dictionnaires et pyspark.sql.Rows , un DataFramepandas et un RDD composé d'une telle liste.
pyspark.sql.SparkSession.createDataFrame prend
l'argument schema pour spécifier le schéma du DataFrame. Lorsqu'il est omis, PySpark déduit le schéma
correspondant en prenant un échantillon des données.

4.2.1 créer un PySpark DataFrame à partir d'une liste de Rows

from datetime import datetime, date


import pandas as pd
from pyspark.sql import Row

df = spark.createDataFrame([
Row(a=1, b=2., c='string1', d=date(2000, 1, 1), e=datetime(2000, 1, 1, 12,
0)),
Row(a=2, b=3., c='string2', d=date(2000, 2, 1), e=datetime(2000, 1, 2, 12,
0)),
Row(a=4, b=5., c='string3', d=date(2000, 3, 1), e=datetime(2000, 1, 3, 12, 0))
])
print(df)

4.2.2 Créez un PySpark DataFrame avec un schéma explicite.


df = spark.createDataFrame([

(1, 2., 'string1', date(2000, 1, 1), datetime(2000, 1, 1, 12, 0)),


(2, 3., 'string2', date(2000, 2, 1), datetime(2000, 1, 2, 12, 0)),
(3, 4., 'string3', date(2000, 3, 1), datetime(2000, 1, 3, 12, 0))
], schema='a long, b double, c string, d date, e timestamp')
print(df)

4.2.3 Créer un DataFrame PySpark à partir d'un DataFrame pandas

pandas_df = pd.DataFrame({
'a': [1, 2, 3],
'b': [2., 3., 4.],
'c': ['string1', 'string2', 'string3'],
'd': [date(2000, 1, 1), date(2000, 2, 1), date(2000, 3, 1)],
'e': [datetime(2000, 1, 1, 12, 0), datetime(2000, 1, 2, 12, 0), datetime(2000,
1, 3, 12, 0)]
})
df = spark.createDataFrame(pandas_df)
print(df)

4.2.4 Créez un PySpark DataFrame à partir d'un RDD composé d'une liste de tuples.

sc = spark.sparkContext
rdd = sc.parallelize([
(1, 2., 'string1', date(2000, 1, 1), datetime(2000, 1, 1, 12, 0)),
(2, 3., 'string2', date(2000, 2, 1), datetime(2000, 1, 2, 12, 0)),
(3, 4., 'string3', date(2000, 3, 1), datetime(2000, 1, 3, 12, 0))

])
df = spark.createDataFrame(rdd, schema=['a', 'b', 'c', 'd', 'e'])
print(df)

Exercice:

#Tester le API suivant

rdd.toDF(['a', 'b', 'c', 'd', 'e'])

Les DataFrames créées ci-dessus ont toutes les mêmes résultats et schéma.
df.show()
df.printSchema()

4.2.5 Affichage des données

df.show(1)
df.collect()

Une dataframe est en effet une liste de Row

4.2.6 Spécifier le schema via StructType.

Les classes PySpark StructType & StructField sont utilisées pour spécifier par programmation le schéma dela
DataFrame et créer des colonnes complexes comme des colonnes imbriquées de structure, de tableau etde carte.
StructType est une collection de StructField qui définit le nom de la colonne, le type de données de la colonne,
booléen pour spécifier si le champ peut être nullable ou non et les métadonnées.
import pyspark
from pyspark.sql import SparkSession
from pyspark.sql.types import StructType,StructField, StringType, IntegerType

struct1 = StructType().add("id", IntegerType(), True).add("name", StringType(),


True, None)
struct2 = StructType([StructField("id", IntegerType(), True), StructField("name",
StringType(), True, None)])
print(struct1 == struct2)

Ensuite nous pouvons passer par exemple struct1 en paramètre dans spark.createDataFrame

data = [("James","","Smith","36636","M",3000),
("Michael","Rose","","40288","M",4000),
("Robert","","Williams","42114","M",4000),
("Maria","Anne","Jones","39192","F",4000),
("Jen","Mary","Brown","","F",-1)
]

schema = StructType([ \
StructField("firstname",StringType(),True), \
StructField("middlename",StringType(),True), \
StructField("lastname",StringType(),True), \
StructField("id", StringType(), True), \
StructField("gender", StringType(), True), \
StructField("salary", IntegerType(), True) \
])

df = spark.createDataFrame(data=data,schema=schema)
df.printSchema()
df.show(truncate=False)

4.2.7 Créez un PySpark DataFrame à partir d'un fichier

Il existe un fichier json dans le dossier du Spark: %Spark_home%/examples/src/main/resources/people.json

par exemple sur mon PC C:\BigDataSoft\spark-3.0.3-bin-


hadoop2.7\examples\src\main\resources\people.json

{"name":"Michael"}
{"name":"Andy", "age":30}
{"name":"Justin", "age":19}
# spark is an existing SparkSession
df = spark.read.json("C:\\BigDataSoft\\spark-3.0.3-bin-
hadoop2.7\\examples\\src\\main\\resources\\people.json")
# Displays the content of the DataFrame to stdout
df.show()

4.3 Operations & requêtes

4.3.1 DSL (domain-specific language) style

En Python, il est possible d'accéder aux colonnes d'un DataFrame soit par attribut (df.age) soit par indexation
(df['age']). Bien que le premier soit pratique pour l'exploration interactive des données, les utilisateurs sont
fortement encouragés à utiliser le dernier formulaire, qui est à l'épreuve du temps et nerompra pas avec les noms de
colonne qui sont également des attributs de la classe DataFrame.

# spark, df are from the previous example


# Print the schema in a tree format
df.printSchema()
# root
# |-- age: long (nullable = true)
# |-- name: string (nullable = true)

# Select only the "name" column


df.select("name").show()
# +-------+
# | name|
# + ----------- +
# |Michael|
# | Andy|
# | Justin|
# + ----------- +

# Select everybody, but increment the age by 1


df.select(df['name'], df['age'] + 1).show()
# +-------+---------+
# | name|(age + 1)|
# +-------+ --------------- +
# |Michael| null|
# | Andy| 31|
# | Justin| 20|
# +-------+---------+

# Select people older than 21


df.filter(df['age'] > 21).show()
# +---+ ------ +
# |age|name|
# +---+----+
# | 30|Andy|
# +---+ ------ +

# Count people by age


df.groupBy("age").count().show()
# +----+-----+
# | age|count|
# +----+ -------- +
# | 19| 1|
# |null| 1|
# | 30| 1|
# +----+-----+

4.3.2 SQL style

La fonction sql sur une SparkSession permet aux applications d'exécuter des requêtes SQL par
programmation et renvoie le résultat sous forme de DataFrame.

# Register the DataFrame as a SQL temporary view


df.createOrReplaceTempView("people")

sqlDF = spark.sql("SELECT * FROM people")


sqlDF.show()

4.4 Agrégation des données

PySpark DataFrame fournit également un moyen de gérer les données groupées en utilisant l'approche commune, la
stratégie fractionner-appliquer-combiner. Il regroupe les données selon une certaine condition,applique une fonction à
chaque groupe, puis les combine à nouveau au DataFrame.

df = spark.createDataFrame([
['red', 'banana', 1, 10], ['blue', 'banana', 2, 20], ['red', 'carrot', 3, 30],
['blue', 'grape', 4, 40], ['red', 'carrot', 5, 50], ['black', 'carrot', 6,

60],
['red', 'banana', 7, 70], ['red', 'grape', 8, 80]], schema=['color', 'fruit',
'v1', 'v2'])
df.show()

Grouping and then applying the avg() function to the resulting groups.

df.groupby('color').avg().show()
En fait groupby renvoie un objet de la classe pyspark.sql.GroupedData . Nous avons donc toutes les
fonctions fonctions d'agrégation classique comme dans SQL: max, min, sum, count, etc

4.5 UDF user defined function

Reprenons la df suivante:

df = spark.createDataFrame([
(1, 2., 'string1', date(2000, 1, 1), datetime(2000, 1, 1, 12, 0)),
(2, 3., 'string2', date(2000, 2, 1), datetime(2000, 1, 2, 12, 0)),
(3, 4., 'string3', date(2000, 3, 1), datetime(2000, 1, 3, 12, 0))

], schema='a long, b double, c string, d date, e timestamp')


print(df)

On veut appliquer la fonction num_10 à cette dataframe, voici le code avec les deux styles introduits ci-dessus.
Faites-attention au nom de la fonction et de la variable utilisée.

#Façon 1: utilisable dans les deux styles


def num_10(num):
return num*10

#Il faut d'abord enregistrer cette fonction


registered_udf = spark.udf.register("registered_func_name", num_10, IntegerType())

#SQL style
df.selectExpr("registered_func_name(a)").show()

#DSL style
df.select(registered_udf(df['a'])).show()
#Façon2 DSL style seul
from pyspark.sql import functions as F
registered_udf2 = F.udf(num_10, IntegerType())
df.select(registered_udf2(df['a'])).show()

4.6 Nettoyage des données

4.6.1 Supprimer des lignes en double

from pyspark.sql import Row


df = sc.parallelize([ \
Row(name='Alice', age=5, height=80), \
Row(name='Alice', age=5, height=80), \
Row(name='Alice', age=10, height=80)]).toDF()
df.dropDuplicates().show()
output :

+-----+---+------+
| name|age|height|
+-----+---+------+
|Alice| 5| 80|
|Alice| 10| 80|
+-----+---+------+

df.dropDuplicates(['name', 'height']).show()

output :

+-----+---+------+
| name|age|height|
+-----+---+------+
|Alice| 5| 80|
+-----+---+------+

4.6.2 traiter des valeurs manquantes

4.6.2.1 dropna()

input_data = [(1, "Shivansh", "Data Scientist", "Noida"),


(2, "Kate", "Software Developer", None),
(3, "Swati", "Data Analyst", "Hyderabad"),
(4, None, None, "Noida"),
(5, "Arpit", "Android Developer", "Banglore"),
(6, "Ritik", None, None),
(None, None, None, None)]
schema = ["Id", "Name", "Job Profile", "City"]

df = spark.createDataFrame(input_data, schema)

df.dropna().show()

output:
+---+--------+-----------------+---------+
| Id| Name| Job Profile| City|
+---+--------+-----------------+---------+
| 1|Shivansh| Data Scientist| Noida|
| 3| Swati| Data Analyst|Hyderabad|
| 5| Arpit|Android Developer| Banglore|
+---+--------+-----------------+---------+

df.dropna(thresh = 3).show()

output:

+---+--------+------------------+---------+
| Id| Name| Job Profile| City|
+---+--------+------------------+---------+
| 1|Shivansh| Data Scientist| Noida|
| 2| Kate|Software Developer| null|
| 3| Swati| Data Analyst|Hyderabad|
| 5| Arpit| Android Developer| Banglore|
+---+--------+------------------+---------+

4.6.2.2 fillna()

df.fillna("loss").show()

output:

+----+--------+------------------+---------+
| Id| Name| Job Profile| City|
+----+--------+------------------+---------+
| 1|Shivansh| Data Scientist| Noida|
| 2| Kate|Software Developer| loss|
| 3| Swati| Data Analyst|Hyderabad|
| 4| loss| loss| Noida|
| 5| Arpit| Android Developer| Banglore|
| 6| Ritik| loss| loss|
|null| loss| loss| loss|
+----+--------+------------------+---------+

df.fillna("loss", subset=["City"]).show()

output:
+----+--------+------------------+---------+
| Id| Name| Job Profile| City|
+----+--------+------------------+---------+
| 1|Shivansh| Data Scientist| Noida|
| 2| Kate|Software Developer| loss|
| 3| Swati| Data Analyst|Hyderabad|
| 4| null| null| Noida|
| 5| Arpit| Android Developer| Banglore|
| 6| Ritik| null| loss|
|null| null| null| loss|
+----+--------+------------------+---------+

4.7 Entrée/sortie de données

Dans la forme la plus simple, la source de données par défaut ( parquet sauf configuration contraire par
spark.sql.sources.default) sera utilisée pour toutes les opérations.

df = spark.read.load("examples/src/main/resources/users.parquet")
df.select("name", "favorite_color").write.save("namesAndFavColors.parquet")

df = spark.read.load("examples/src/main/resources/people.csv",
format="csv", sep=";", inferSchema="true", header="true")

df = spark.read.load("examples/src/main/resources/people.json", format="json")
df.select("name", "age").write.save("namesAndAges.parquet", format="parquet")

df.write.csv('foo.csv', header=True)
spark.read.csv('foo.csv', header=True).show()

Vous aimerez peut-être aussi