au cluster choisi • Déploie les ressources vers le cluster • Lance le driver sur la machine locale (client mode) ou demande l’execution au cluster manager (cluster mode) 27
cluster --packages my.fab:spark-job:1.2.2 --class my.fab.JobClass dummy ... 151 WARN [main] DependencyUtils: Local jar /Users/raphael/dummy does not exist, skipping. ... 28
d'exécution des requêtes Dataset & SQL Tungsten: Ensemble d'optimisation techniques notamment pour réduire la pression mémoire et augmenter l'efficacité CPU
[cast(nature#19 as string) AS nature#7284, cast(count#7276L as string) AS count#7285] +- Aggregate [nature#19], [nature#19, count(1) AS count#7276L] +- Relation[id#10,id_ex#11,siret#12,rup_mi#13,gestion#14,d ate_creat#15,date_decla#16,date_publi#17,date_disso#18, nature#19,groupement#20,titre#21,titre_court#22,objet#2 3,objet_social1#24,objet_social2#25,adrs_complement#26, adrs_numvoie#27,adrs_repetition#28,adrs_typevoie#29,adr s_libvoie#30,adrs_distrib#31,adrs_codeinsee#32,adrs_cod epostal#33,... 15 more fields] csv 55
du graphe de dépendance pour accélérer les traitements : - PartitionPruning - PredicatePushdown - ProjectionPushdown ... + les règles de l'algèbre relationnel
sources de données pour sélectionner le meilleur plan physique parmi tous les plans possibles. Principal impact sur les opérations "join" Optimized Plan Physical Plan Physical Plan Physical Plan Physical Plan Physical Plan Physical Plan Physical Plan Physical Plan Physical Plan
Ne fonctionne que sur tables Nécessite un calcul préalable des statistiques ANALYZE TABLE mutable COMPUTE STATISTICS ANALYZE TABLE mutable COMPUTE STATISTICS FOR COLUMNS col1, col2
regrouper les données en des groupes ayant un sens df.repartition('dpt) .write .partitionBy("dpt") .parquet("my_dataset") 1 seul fichier de sortie par partition sur disque
et queueing policy YARN Mono-tenant: Limité par parallélisme des données et des stages Allocation dynamique permet de simplifier cette gestion au prix d’une latence de job un peu plus élevée
de partage de données intra-process - augmente les temps de full-GC - (HDFS) peut créer de la contention d’I/O Plus d’exécuteurs: - plus de shuffle - plus simple à allouer par le cluster manager
taille mémoire pour maximiser l’utilisation du noeud. 2 à 4G/core est une bonne base Laisser des ressources à l'OS Prendre en compte le YARN memoryOverhead (10% heap par défaut) Pour valider, mesurez les différences de performance entre configurations !
192 GB RAM 1 core pour OS, ~5 à 10% RAM pour OS/Cache disque -> YARN peut allouer au plus 47 cores et 180 G RAM On prend 5 cores / executor -> 9 executors soit 20 GB total/ executor Yarn memoryOverhead = 10 à 15% donc on fixe heap a 18G —num-executors 9 —executor-cores 5 —executor-memory 18G
mais coûteux dans le cas général 1 shuffle + 2 sorts Si Spark détecte qu'un des 2 datasets est "petit", il va utiliser un BroadcastHashJoin à la place Si Spark sait que les 2 datasets sont déjà partitionnés de manière équivalentes (bucket), il va éviter le shuffle
metastore), "pre shuffle persistant" d'un dataset. df.repartition(30,'year,'key) .write .partitionBy("year") .bucketBy(30,"key") .sortBy("key") .saveAsTable("my_table") Bucketing accélère group by, join et windowing sur les colonnes concernées
gérer le skew (déséquilibre de données): - ajouter un sel pour mieux répartir les clés et agréger en 2 étapes - avoir 2 traitements différents pour la clé dominante et le reste (typiquement NULL handling) - accepter le skew si le delta de temps n'est pas trop important
est trop petite pour tout accueillir, une partie de la mémoire est copiée sur disque et libérée Partie exécution n'est jamais spilled, toujours storage Si le storage est non vide, il ne peut pas être spilled en dessous du spark.memory.storageFraction Spark a besoin de maxPartitionSize * executor-cores en unified memory pour l'execution de toutes les tasks en parallèle
métriques ! • Ajuster le spark.memory.fraction • Adapter le GC (plutôt G1GC ou ParallelGC) • Réduire l'utilisation des UDF et opérations Dataset • Diminuer le poids des structures de données 95
49.2 in stage 6.0 (TID xxx, xxx.xxx.xxx.compute.internal): ExecutorLostFailure (executor 16 exited caused by one of the running tasks) Reason: Container killed by YARN for exceeding memory limits. 10.4 GB of 10.4 GB physical memory used. Consider boosting spark.yarn.executor.memoryOverhead.
spark.shuffle.io.preferDirectBufs=false Limiter et déclarer la RAM pour le process Python spark.executor.pyspark.memory=XXXM Augmenter le memory overhead spark.executor.memoryOverhead=15% heap
spark.shuffle.io.preferDirectBufs=false Limiter et déclarer la RAM pour le process Python spark.executor.pyspark.memory=XXXM Augmenter le memory overhead spark.executor.memoryOverhead=15% heap
compressés directement mais ne supporte pas .zip ou .7z En interne, Spark utilise LZ4 par défaut pour la compression des shuffles, spills et broadcast. Pour améliorer les taux de compression: spark.io.compression.lz4.blockSize=128k ou 256k
Plan Physical Plan Task RDD Physical Plan Physical Plan Physical Plan Physical Plan Physical Plan Meta-données Règles heuristiques Statistiques Codegen Catalog
le driver • Pensez utilisation ultérieure du dataset (partition by, sort by, bucket by) • Surveiller le nombre de fichiers d'output • Maximiser le parallélisme des traitements 116