Imp. TIP:
Setiap kali Anda memiliki inisialisasi kelas berat yang harus dilakukan satu kali untuk banyak RDD
elemen daripada satu kali per RDD
elemen, dan jika inisialisasi ini, seperti pembuatan objek dari perpustakaan pihak ketiga, tidak dapat diserialisasi (sehingga Spark dapat mengirimkannya melintasi gugus ke node pekerja), gunakan mapPartitions()
sebagai ganti
map()
. mapPartitions()
menyediakan inisialisasi yang harus dilakukan sekali per tugas pekerja / utas / partisi bukannya sekali per RDD
elemen data misalnya: lihat di bawah.
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. apakah flatMap
berperilaku seperti peta atau suka mapPartitions
?
Iya. silakan lihat contoh 2 dari flatmap
.. penjelasannya sendiri.
Q1. Apa perbedaan antara RDD map
danmapPartitions
map
berfungsi dengan fungsi yang digunakan pada level per elemen sambil
mapPartitions
menjalankan fungsi di level partisi.
Skenario Contoh : jika kita memiliki elemen 100K diRDD
partisitertentumaka kita akan menjalankan fungsi yang digunakan oleh transformasi pemetaan 100K kali ketika kita gunakanmap
.
Sebaliknya, jika kita menggunakan mapPartitions
maka kita hanya akan memanggil fungsi tertentu satu kali, tetapi kita akan melewati semua catatan 100 ribu dan mendapatkan kembali semua tanggapan dalam satu panggilan fungsi.
Akan ada perolehan kinerja karena map
bekerja pada fungsi tertentu berkali-kali, terutama jika fungsi tersebut melakukan sesuatu yang mahal setiap kali itu tidak perlu dilakukan jika kita melewati semua elemen sekaligus (dalam kasus mappartitions
).
peta
Menerapkan fungsi transformasi pada setiap item RDD dan mengembalikan hasilnya sebagai RDD baru.
Daftar Varian
def map [U: ClassTag] (f: T => U): RDD [U]
Contoh:
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
Ini adalah peta khusus yang hanya dipanggil sekali untuk setiap partisi. Seluruh konten partisi masing-masing tersedia sebagai aliran nilai berurutan melalui argumen input (Iterarator [T]). Fungsi kustom harus mengembalikan Iterator [U] lainnya. Iterator hasil gabungan secara otomatis dikonversi menjadi RDD baru. Harap dicatat, bahwa tupel (3,4) dan (6,7) hilang dari hasil berikut karena partisi yang kami pilih.
preservesPartitioning
menunjukkan apakah fungsi input mempertahankan partisi, yang seharusnya false
kecuali ini adalah RDD pasangan dan fungsi input tidak mengubah kunci.
Daftar Varian
def mapPartitions [U: ClassTag] (f: Iterator [T] => Iterator [U], preservesPartitioning: Boolean = false): RDD [U]
Contoh 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))
Contoh 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)
Program di atas juga dapat ditulis menggunakan flatMap sebagai berikut.
Contoh 2 menggunakan 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)
Kesimpulan:
mapPartitions
transformasi lebih cepat daripada map
karena memanggil fungsi Anda sekali / partisi, bukan sekali / elemen ..
Bacaan lebih lanjut: foreach Vs foreachPartitions Kapan menggunakan What?