Quelle est la différence entre une méthode RDDmap
et mapPartitions
? Et est-ce que flatMap
se comporte comme map
ou comme mapPartitions
? Merci.
(modifier) c’est-à-dire quelle est la différence (soit sémantiquement, soit en termes d’exécution) entre
def map[A, B](rdd: RDD[A], fn: (A => B))
(implicit a: Manifest[A], b: Manifest[B]): RDD[B] = {
rdd.mapPartitions({ iter: Iterator[A] => for (i <- iter) yield fn(i) },
preservesPartitioning = true)
}
Et:
def map[A, B](rdd: RDD[A], fn: (A => B))
(implicit a: Manifest[A], b: Manifest[B]): RDD[B] = {
rdd.map(fn)
}
Quelle est la différence entre la carte et la méthode mapPartitions d'un RDD?
La méthode map convertit chaque élément du RDD source en un seul élément du résultat RDD en appliquant une fonction. mapPartitions convertit chaque partition du RDD source en plusieurs éléments du résultat (éventuellement aucun).
Et flatMap se comporte-t-il comme une carte ou comme mapPartitions?
Ni l'un ni l'autre flatMap ne fonctionne sur un seul élément (sous la forme map
) et génère plusieurs éléments du résultat (sous la forme mapPartitions
).
Chaque fois que vous avez une initialisation lourde à effectuer une fois pour plusieurs éléments
RDD
plutôt qu'une fois par élémentRDD
, et si cette initialisation, telle que la création d'objets à partir d'une bibliothèque tierce, ne peut pas être sérialisée (de sorte que Spark peut le transmettre à travers le cluster aux nœuds de travail), utilisezmapPartitions()
au lieu demap()
.mapPartitions()
prévoit que l'initialisation doit être effectuée une fois par tâche de travail/unité d'exécution/partition au lieu d'une fois par élément de donnéesRDD
pour exemple: voir ci-dessous.
val newRd = myRdd.mapPartitions(partition => {
val connection = new DbConnection /*creates a db connection per partition*/
val newPartition = partition.map(record => {
readMatchingFromDB(record, connection)
}).toList // consumes the iterator, thus calls readMatchingFromDB
connection.close() // close dbconnection here
newPartition.iterator // create a new iterator
})
Q2.
flatMap
se comporte-t-il comme map ou commemapPartitions
?
Oui. veuillez vous reporter à l'exemple 2 de flatmap
.. son explicite.
Q1. Quelle est la différence entre les noms
map
etmapPartitions
map
utilise la fonction utilisée au niveau de chaque élément alors quemapPartitions
l'exerce au niveau de la partition.
Exemple de scénario : Si nous avons 100 000 éléments dans une partition RDD
particulière, nous lancerons la fonction. utilisé par la transformation de mappage 100 000 fois lorsque nous utilisons map
.
Inversement, si nous utilisons mapPartitions
, nous n'appellerons cette fonction qu'une seule fois, mais nous transmettrons tous les enregistrements de 100 000 et nous récupérons toutes les réponses en un seul appel.
Il y aura un gain de performance car map
fonctionne tellement souvent sur une fonction particulière, surtout si la fonction effectue quelque chose de coûteux à chaque fois qu'elle n'aurait pas besoin de le faire si nous transmettions tous les éléments à la fois ( dans le cas de mappartitions
).
Applique une fonction de transformation à chaque élément du RDD et renvoie le résultat sous la forme d'un nouveau RDD.
Liste des variantes
def map [U: ClassTag] (f: T => U): RDD [U]
Exemple :
val a = sc.parallelize(List("dog", "salmon", "salmon", "rat", "elephant"), 3)
val b = a.map(_.length)
val c = a.Zip(b)
c.collect
res0: Array[(String, Int)] = Array((dog,3), (salmon,6), (salmon,6), (rat,3), (elephant,8))
Il s'agit d'une carte spécialisée appelée une seule fois pour chaque partition. L'ensemble du contenu des partitions respectives est disponible sous forme de flux séquentiel de valeurs via l'argument d'entrée (Iterarator [T]). La fonction personnalisée doit renvoyer un autre Iterator [U]. Les itérateurs de résultats combinés sont automatiquement convertis en un nouveau RDD. Veuillez noter que les tuples (3,4) et (6,7) sont absents du résultat suivant en raison du partitionnement choisi.
preservesPartitioning
indique si la fonction d'entrée conserve le partitionneur, qui devrait êtrefalse
à moins qu'il ne s'agisse d'une paire RDD et que la fonction d'entrée ne modifie pas les clés.Variantes de référencement
def mapPartitions [U: ClassTag] (f: Iterator [T] => Iterator [U], preserveesPartitioning: Boolean = false): RDD [U]
Exemple 1
val a = sc.parallelize(1 to 9, 3)
def myfunc[T](iter: Iterator[T]) : Iterator[(T, T)] = {
var res = List[(T, T)]()
var pre = iter.next
while (iter.hasNext)
{
val cur = iter.next;
res .::= (pre, cur)
pre = cur;
}
res.iterator
}
a.mapPartitions(myfunc).collect
res0: Array[(Int, Int)] = Array((2,3), (1,2), (5,6), (4,5), (8,9), (7,8))
Exemple 2
val x = sc.parallelize(List(1, 2, 3, 4, 5, 6, 7, 8, 9,10), 3)
def myfunc(iter: Iterator[Int]) : Iterator[Int] = {
var res = List[Int]()
while (iter.hasNext) {
val cur = iter.next;
res = res ::: List.fill(scala.util.Random.nextInt(10))(cur)
}
res.iterator
}
x.mapPartitions(myfunc).collect
// some of the number are not outputted at all. This is because the random number generated for it is zero.
res8: Array[Int] = Array(1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 7, 7, 7, 9, 9, 10)
Le programme ci-dessus peut également être écrit en utilisant flatMap comme suit.
Exemple 2 en utilisant flatmap
val x = sc.parallelize(1 to 10, 3)
x.flatMap(List.fill(scala.util.Random.nextInt(10))(_)).collect
res1: Array[Int] = Array(1, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10)
La transformation mapPartitions
est plus rapide que map
puisqu'elle appelle votre fonction une fois/partition, pas une fois/élément ..
Lectures supplémentaires: foreach Vs foreachPartitions Quand utiliser quoi?
Carte :
- Il traite une ligne à la fois, très similaire à la méthode map () de MapReduce.
- Vous revenez de la transformation après chaque ligne.
MapPartitions
- Il traite la partition complète en une fois.
- Vous ne pouvez quitter la fonction qu'une seule fois après avoir traité toute la partition.
- Tous les résultats intermédiaires doivent être conservés en mémoire jusqu'à ce que vous traitiez la partition entière.
- Vous fournit les fonctions setup () map () et cleanup () de MapReduce
Map Vs mapPartitions
http://bytepadding.com/big-data/spark/spark-map-vs-mappartitions/
Spark Map
http://bytepadding.com/big-data/spark/spark-map/
Spark mapPartitions
http://bytepadding.com/big-data/spark/spark-mappartitions/