İ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 RDD
ve üçü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 RDD
veri öğ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 flatMap
uslu 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 map
vemapPartitions
map
işlevi mapPartitions
bölüm düzeyinde uygularken , kullanılan işlevi öğe başına
düzeyinde çalıştırır.
Örnek Senaryo : Belirli birRDD
bö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, mapPartitions
o 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.
map
Belirli 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.
preservesPartitioning
giriş işlevinin bölümleyiciyi koruyup korumadığını gösterir; false
bu, 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ç:
mapPartitions
dönüşüm, map
iş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?