İth. İPUCU :
Her RDDöğe için bir kez yerine birçok öğe için bir kez yapılması gereken ağır başlatmanız olduğunda RDDve üçüncü taraf kitaplıktan nesnelerin oluşturulması gibi bu başlatma serileştirilemezse (böylece Spark bunu küme boyunca iletebilir. işçi düğümleri), mapPartitions()yerine
kullanın map(). Örneğin,mapPartitions() her RDDveri öğesi için bir kez yerine çalışan görevi / iş parçacığı / bölüm başına bir kez başlatmanın yapılmasını sağlar : aşağıya bakın.
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
})
S2. does flatMapuslu haritası gibi ya da benzeri mapPartitions?
Evet. lütfen 2. örneğe bakın flatmap, kendini açıklayıcı.
S1. Bir RDD en arasındaki fark nedir mapvemapPartitions
mapişlevi mapPartitionsbölüm düzeyinde uygularken , kullanılan işlevi öğe başına
düzeyinde çalıştırır.
Örnek Senaryo : Belirli birRDDbölümde100K öğemiz varsa, kullandığımızda eşleme dönüşümü tarafından kullanılan işlevi 100K kez ateşleyeceğizmap.
Tersine, eğer kullanırsak, mapPartitionso zaman belirli bir işlevi yalnızca bir kez çağıracağız, ancak tüm 100K kayıtları aktaracağız ve tüm yanıtları bir işlev çağrısında geri alacağız.
mapBelirli bir işlev üzerinde pek çok kez çalıştığından, özellikle işlev her seferinde tüm öğeleri aynı anda geçsek (olması durumunda mappartitions) yapması gerekmeyecek pahalı bir şey yapıyorsa, performans kazanımı olacaktır .
harita
RDD'nin her öğesine bir dönüştürme işlevi uygular ve sonucu yeni bir RDD olarak döndürür.
Listeleme Varyantları
def eşleme [U: ClassTag] (f: T => U): RDD [U]
Misal :
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))
mapPartitions
Bu, her bölüm için yalnızca bir kez çağrılan özel bir haritadır. İlgili bölümlerin tüm içeriği, giriş bağımsız değişkeni (Yineleyici [T]) aracılığıyla sıralı bir değer akışı olarak kullanılabilir. Özel işlev, başka bir Yineleyici [U] döndürmelidir. Birleşik sonuç yineleyiciler otomatik olarak yeni bir RDD'ye dönüştürülür. Lütfen, seçtiğimiz bölümleme nedeniyle tuple (3,4) ve (6,7) 'nin aşağıdaki sonuçta eksik olduğunu unutmayın.
preservesPartitioninggiriş işlevinin bölümleyiciyi koruyup korumadığını gösterir; falsebu, bu bir çift RDD değilse ve giriş işlevi tuşları değiştirmez.
Listeleme Varyantları
def mapPartitions [U: ClassTag] (f: Iterator [T] => Iterator [U], preservesPartitioning: Boolean = false): RDD [U]
örnek 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))
Örnek 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)
Yukarıdaki program aşağıdaki gibi flatMap kullanılarak da yazılabilir.
Örnek 2 Flatmap kullanarak
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)
Sonuç:
mapPartitionsdönüşüm, mapişlevinizi bir kez / element değil, bir kez / bölüm çağırdığından daha hızlıdır ..
Daha fazla okuma: foreach Vs foreachPartitions Ne zaman Ne kullanılır?