Imp। सुझाव:
जब भी आपके पास हैवीवेट इनिशियलाइज़ेशन हो जो एक RDD
तत्व के बजाय कई तत्वों के लिए एक बार किया जाना चाहिए RDD
, और यदि यह इनिशियलाइज़ेशन, जैसे कि किसी थर्ड-पार्टी लाइब्रेरी से ऑब्जेक्ट्स का निर्माण, को क्रमबद्ध नहीं किया जा सकता है (ताकि स्पार्क इसे क्लस्टर में प्रसारित कर सके। कार्यकर्ता नोड्स), के mapPartitions()
बजाय का
उपयोग करें map()
। उदाहरण के लिए mapPartitions()
एक बार RDD
डेटा तत्व के अनुसार श्रमिक कार्य / थ्रेड / विभाजन के अनुसार एक बार किए जाने के लिए आरंभिकता प्रदान करता है : नीचे देखें।
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
या पसंद करता है mapPartitions
?
हाँ। कृपया देखें उदाहरण 2 का flatmap
.. इसकी स्व व्याख्या।
Q1। एक RDD के बीच क्या अंतर है map
औरmapPartitions
map
mapPartitions
विभाजन के स्तर पर कार्य का अभ्यास करते हुए एक तत्व स्तर पर उपयोग किए जा रहे फ़ंक्शन को काम करता
है।
उदाहरण परिदृश्य : यदि हमारे पास किसी विशेषRDD
विभाजनमें 100K तत्व हैंतो हम उपयोग किए जा रहे फ़ंक्शन को मैपिंग परिवर्तन 100K बार बंद कर देंगेmap
।
इसके विपरीत, अगर हम उपयोग करते हैं mapPartitions
तो हम केवल एक बार विशेष फ़ंक्शन को कॉल करेंगे, लेकिन हम सभी 100K रिकॉर्ड में पास होंगे और एक फ़ंक्शन कॉल में सभी प्रतिक्रियाएं वापस प्राप्त करेंगे।
map
किसी विशेष फ़ंक्शन पर कई बार काम करने के बाद से प्रदर्शन लाभ होगा , खासकर यदि फ़ंक्शन हर बार कुछ महंगा कर रहा है, तो यह करने की आवश्यकता नहीं होगी यदि हम एक बार में सभी तत्वों में पारित हो गए (मामले में mappartitions
)।
नक्शा
RDD के प्रत्येक आइटम पर एक परिवर्तन फ़ंक्शन लागू करता है और एक नए RDD के रूप में परिणाम देता है।
सूचीबद्ध वेरिएंट
डिफ मैप [U: ClassTag] (f: T => U): RDD [U]
उदाहरण :
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
यह एक विशेष नक्शा है जिसे प्रत्येक विभाजन के लिए केवल एक बार कहा जाता है। संबंधित विभाजनों की संपूर्ण सामग्री इनपुट तर्क (Iterarator [T]) के माध्यम से मूल्यों की एक अनुक्रमिक धारा के रूप में उपलब्ध है। कस्टम फ़ंक्शन को एक और Iterator [U] लौटना चाहिए। संयुक्त परिणाम पुनरावृत्तियों स्वचालित रूप से एक नए RDD में परिवर्तित हो जाते हैं। कृपया ध्यान दें, हमारे द्वारा चुने गए विभाजन के कारण ट्यूपल्स (3,4) और (6,7) निम्नलिखित परिणाम से गायब हैं।
preservesPartitioning
इंगित करता है कि क्या इनपुट फ़ंक्शन पार्टीशनर को संरक्षित करता है, जो false
तब तक होना चाहिए जब तक कि यह एक जोड़ी आरडीडी नहीं है और इनपुट फ़ंक्शन कुंजियों को संशोधित नहीं करता है।
सूचीबद्ध वेरिएंट
def mapPartitions [U: ClassTag] (f: Iterator [T] => Iterator [U], संरक्षित करता है: Boolean = false): RDD [U]
उदाहरण 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))
उदाहरण 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)
उपर्युक्त कार्यक्रम को फ्लैटपाइप का उपयोग करके भी लिखा जा सकता है।
उदाहरण 2 सपाट का उपयोग कर
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)
निष्कर्ष:
mapPartitions
परिवर्तन तेजी से है map
क्योंकि यह आपके फ़ंक्शन को एक बार / विभाजन कहता है, एक बार / तत्व नहीं ..
आगे पढ़े: foreach Vs foreachPartitions कब इस्तेमाल करें?