स्पार्क - रिपर्टिशन () बनाम कॉलेसस ()


254

लर्निंग स्पार्क के अनुसार

ध्यान रखें कि आपके डेटा को पुन: प्रस्तुत करना एक काफी महंगा ऑपरेशन है। स्पार्क भी की एक अनुकूलित संस्करण है repartition()कहा जाता coalesce()है कि डेटा आंदोलन से बचने की अनुमति देता है, लेकिन केवल तभी जब आप RDD विभाजन की संख्या कम कर रहे हैं।

एक अंतर मुझे यह है कि repartition()विभाजन की संख्या के साथ वृद्धि / कमी की जा सकती है, लेकिन coalesce()विभाजन की संख्या के साथ ही घटाई जा सकती है।

यदि विभाजन कई मशीनों में फैले हुए हैं और coalesce()चलाए जा रहे हैं, तो यह डेटा आंदोलन से कैसे बच सकता है?

जवाबों:


354

यह एक पूर्ण फेरबदल से बचा जाता है । यदि यह ज्ञात है कि संख्या कम हो रही है, तो निष्पादक न्यूनतम संख्याओं पर डेटा को सुरक्षित रूप से रख सकता है, केवल अतिरिक्त नोड्स से डेटा को स्थानांतरित करके, हमारे द्वारा रखे गए नोड्स पर।

तो, यह कुछ इस तरह होगा:

Node 1 = 1,2,3
Node 2 = 4,5,6
Node 3 = 7,8,9
Node 4 = 10,11,12

फिर coalesceनीचे 2 विभाजन:

Node 1 = 1,2,3 + (10,11,12)
Node 3 = 7,8,9 + (4,5,6)

ध्यान दें कि नोड 1 और नोड 3 को स्थानांतरित करने के लिए अपने मूल डेटा की आवश्यकता नहीं थी।


115
जवाब देने के लिए धन्यवाद। प्रलेखन के minimize data movementबजाय बेहतर कहा जाना चाहिए था avoiding data movement
प्रवीण श्रीपति

12
क्या कोई ऐसा मामला है जब repartitionइसके बजाय उपयोग किया जाना चाहिए coalesce?
नीमंद

21
@ नीमंद मुझे लगता है कि मौजूदा प्रलेखन में यह बहुत अच्छी तरह से शामिल है: github.com/apache/spark/blob/… ध्यान रखें कि यह सब सच है सेट पैरामीटर के साथ repartitionकॉल है। यदि इससे सहायता मिलती है तो मुझे बताएं। coalesceshuffle
जस्टिन पिहोनी

2
क्या मौजूदा फ़ाइलों की संख्या को कम करना संभव है जो मौजूदा हैं? मेरे पास कोई hdfs नहीं है, लेकिन कई फाइलों के साथ समस्या है।

2
पुनरावृत्ति सांख्यिकीय रूप से धीमी हो जाएगी क्योंकि यह नहीं जानता कि यह सिकुड़ रहा है ... हालांकि शायद वे इसे अनुकूलित कर सकते हैं। आंतरिक रूप से यह सिर्फ एक shuffle = trueध्वज के साथ
सहसंबंध

172

जस्टिन का जवाब बहुत बढ़िया है और यह प्रतिक्रिया अधिक गहराई में जाती है।

repartitionएल्गोरिथ्म एक पूर्ण फेरबदल करता है और डेटा है कि समान रूप से वितरित है के साथ नए विभाजन पैदा करता है। 1 से 12 तक की संख्या के साथ एक DataFrame बनाते हैं।

val x = (1 to 12).toList
val numbersDf = x.toDF("number")

numbersDf मेरी मशीन पर 4 विभाजन हैं।

numbersDf.rdd.partitions.size // => 4

यहां बताया गया है कि डेटा को विभाजन पर कैसे विभाजित किया जाता है:

Partition 00000: 1, 2, 3
Partition 00001: 4, 5, 6
Partition 00002: 7, 8, 9
Partition 00003: 10, 11, 12

आइए repartitionविधि के साथ एक पूर्ण-फेरबदल करें और दो नोड्स पर यह डेटा प्राप्त करें।

val numbersDfR = numbersDf.repartition(2)

यहां बताया गया है कि numbersDfRमेरी मशीन पर डेटा कैसे विभाजित किया जाता है:

Partition A: 1, 3, 4, 6, 7, 9, 10, 12
Partition B: 2, 5, 8, 11

repartitionविधि नया विभाजन बनाता है और समान रूप से नया विभाजन में डेटा वितरित करता है (डेटा वितरण और भी बड़े डेटा सेट के लिए है)।

coalesceऔर के बीच अंतरrepartition

coalesceमौजूदा विभाजन का उपयोग करता है, जो कि फेरबदल किए गए डेटा की मात्रा को कम करता है। repartitionनए विभाजन बनाता है और एक पूर्ण फेरबदल करता है। coalesceअलग-अलग मात्रा में डेटा के साथ विभाजन में परिणाम (कभी-कभी ऐसे विभाजन जिनमें बहुत अधिक आकार होते हैं) और repartitionपरिणाम लगभग बराबर आकार के विभाजन के होते हैं।

है coalesceया repartitionतेजी से?

coalesceकी तुलना में तेजी से चल सकता है repartition, लेकिन असमान आकार के विभाजन समान आकार के विभाजन की तुलना में काम करने के लिए आमतौर पर धीमे होते हैं। एक बड़े डेटा सेट को फ़िल्टर करने के बाद आपको आमतौर पर डेटासेट को पुन: प्रारंभ करना होगा। मैंने repartitionसमग्र रूप से तेजी से पाया है क्योंकि स्पार्क समान आकार के विभाजन के साथ काम करने के लिए बनाया गया है।

एनबी मैंने उत्सुकता से देखा है कि पुनरावृत्ति डिस्क पर डेटा का आकार बढ़ा सकती है । जब आप बड़े डेटासेट पर रिपार्ट / कॉलेसे का उपयोग कर रहे हों, तो परीक्षण चलाना सुनिश्चित करें।

यदि आप और भी अधिक विवरण चाहते हैं तो इस ब्लॉग पोस्ट को पढ़ें

जब आप अभ्यास में सहवास और पुनरावृत्ति का उपयोग करेंगे


8
शानदार उत्तर @ पॉवर्स, लेकिन विभाजन ए और बी में डेटा तिरछा नहीं है? इसे समान रूप से कैसे वितरित किया जाता है?
अनवरथेवियन

इसके अलावा, OOM त्रुटि प्राप्त किए बिना विभाजन आकार प्राप्त करने का सबसे अच्छा तरीका क्या है। मैं उपयोग करता हूं rdd.glom().map(len).collect()लेकिन यह OOM की बहुत सारी त्रुटियां देता है।
अनवरथेवियन

8
@anwartheravian - विभाजन ए और विभाजन बी विभिन्न आकार हैं क्योंकि repartitionएल्गोरिथ्म डेटा को बहुत छोटे डेटा सेटों के लिए समान रूप से वितरित नहीं करता है। मैं repartition13 विभाजन में 5 मिलियन रिकॉर्ड का आयोजन करता था और प्रत्येक फ़ाइल 89.3 एमबी और 89.6 एमबी के बीच थी - यह बहुत ही बराबर है!
शक्तियां

1
@ इस विस्तार के साथ बेहतर जवाब देखो।
ग्रीन

1
यह अंतर को काफी बेहतर बताता है। धन्यवाद!
अभि

22

यहां एक और ध्यान देने वाली बात यह है कि स्पार्क आरडीडी का मूल सिद्धांत अपरिवर्तनीयता है। पुनरावृत्ति या जमाव नए RDD का निर्माण करेगा। आधार RDD का विभाजन की मूल संख्या के साथ अस्तित्व बना रहेगा। यदि उपयोग मामला आरडीडी को कैश में बनाए रखने की मांग करता है, तो नए बनाए गए आरडीडी के लिए भी ऐसा ही करना होगा।

scala> pairMrkt.repartition(10)
res16: org.apache.spark.rdd.RDD[(String, Array[String])] =MapPartitionsRDD[11] at repartition at <console>:26

scala> res16.partitions.length
res17: Int = 10

scala>  pairMrkt.partitions.length
res20: Int = 2

अच्छा है! यह महत्वपूर्ण है और कम से कम इस अनुभवी स्कैला देव के लिए, स्पष्ट नहीं है - यानी, न तो पुनरावृत्ति और न ही डेटा को संशोधित करने के लिए कठोर प्रयास, बस इसे नोड्स में कैसे वितरित किया जाता है
doug

1
@ हरिकृष्णन इसलिए अगर मैं अन्य उत्तरों को ठीक से समझ पाया तो उनके अनुसार कोक्लेसी के मामले में स्पार्क मौजूदा विभाजनों का उपयोग करता है, लेकिन आरडीडी अपरिवर्तनीय है, क्या आप बता सकते हैं कि कोलेससे मौजूदा विभाजनों का उपयोग कैसे करते हैं? मेरी समझ के अनुसार, मैंने सोचा कि स्पार्क तालमेल में मौजूदा विभाजनों में नए विभाजन को जोड़ता है।
एक्सप्लोरर

लेकिन अगर "पुराने" आरडीडी का उपयोग नहीं किया जाता है, जैसा कि निष्पादन ग्राफ द्वारा जाना जाता है, तो यह मेमोरी से साफ हो जाएगा यदि निरंतर नहीं है, तो क्या यह नहीं होगा?
मार्कस

15

repartition - विभाजन की संख्या में वृद्धि करते हुए इसका उपयोग करने की अनुशंसा की जाती है, क्योंकि इसमें सभी डेटा का फेरबदल शामिल है।

coalesce- विभाजन की संख्या को कम करते हुए इसका उपयोग करने की अनुशंसा की जाती है। उदाहरण के लिए यदि आपके पास 3 विभाजन हैं और आप इसे 2 पर कम करना चाहते हैं, coalesceतो 3 विभाजन डेटा को विभाजन 1 में ले जाएगा और 2 विभाजन 1 और 2 एक ही कंटेनर में रहेगा। दूसरी ओर, repartitionसभी विभाजनों में डेटा फेरबदल करेगा, इसलिए निष्पादकों के बीच नेटवर्क का उपयोग अधिक होगा और यह प्रदर्शन को प्रभावित करेगा।

coalescerepartitionविभाजन की संख्या को कम करते हुए बेहतर प्रदर्शन करता है ।


उपयोगी स्पष्टीकरण।
नरेंद्र मारू

11

कोड और कोड डॉक्स से इस प्रकार है कि coalesce(n)जैसा है वैसा ही है coalesce(n, shuffle = false)और repartition(n)जैसा हैcoalesce(n, shuffle = true)

इस प्रकार, दोनों coalesceका repartitionउपयोग विभाजन की संख्या बढ़ाने के लिए किया जा सकता है

इसके साथ shuffle = true, आप वास्तव में बड़ी संख्या में विभाजन के लिए तैयार हो सकते हैं। यह उपयोगी है यदि आपके पास विभाजन की एक छोटी संख्या है, तो 100 कहें, संभावित रूप से कुछ विभाजन असामान्य रूप से बड़े हैं।

उच्चारण करने के लिए एक और महत्वपूर्ण नोट यह है कि यदि आप विभाजन की संख्या में भारी कमी करते हैं, तो आपको ( उस मामले में भी) के फेरबदल संस्करण का उपयोग करने पर विचार करना चाहिए । यह आपकी गणनाओं को मूल विभाजन (एकाधिक कार्य) पर समानांतर में करने की अनुमति देगा ।coalescerepartition

हालाँकि, यदि आप एक कठोर तालमेल कर रहे हैं, उदाहरण के लिए numPartitions = 1, यह आपके संगणना के परिणामस्वरूप कम नोड्स पर जगह ले सकता है जैसे आप (जैसे मामले में एक नोड numPartitions = 1)। इससे बचने के लिए, आप पास कर सकते हैं shuffle = true। यह एक फेरबदल कदम को जोड़ देगा, लेकिन इसका मतलब है कि वर्तमान अपस्ट्रीम विभाजन को समानांतर में निष्पादित किया जाएगा (जो भी वर्तमान विभाजन है)।

कृपया संबंधित जवाब यहां भी देखें


10

सभी उत्तर इस महान अक्सर पूछे जाने वाले प्रश्न में कुछ महान ज्ञान जोड़ रहे हैं।

इसलिए इस प्रश्न की समयरेखा की परंपरा के अनुसार, यहाँ मेरे 2 सेंट हैं।

मैंने पाया कि पुनरावृत्ति बहुत ही विशिष्ट मामले में, मोटे से तेज है

मेरे आवेदन में जब हम अनुमान लगाने वाली फ़ाइलों की संख्या निश्चित सीमा से कम है, तो पुनरावृत्ति तेजी से काम करती है।

यही है जो मेरा मतलब है

if(numFiles > 20)
    df.coalesce(numFiles).write.mode(SaveMode.Overwrite).parquet(dest)
else
    df.repartition(numFiles).write.mode(SaveMode.Overwrite).parquet(dest)

उपरोक्त स्निपेट में, यदि मेरी फाइलें 20 से कम थीं, तो कॉल्ससेर हमेशा के लिए खत्म हो रहा था, जबकि पुनरावृत्ति बहुत तेज थी और इसलिए उपरोक्त कोड।

बेशक, यह संख्या (20) श्रमिकों की संख्या और डेटा की मात्रा पर निर्भर करेगी।

उम्मीद है की वो मदद करदे।


6

पुनर्मूल्यांकन : नए विभाजन में डेटा को फेरबदल करें।

उदाहरण के लिए। प्रारंभिक डेटा फ़्रेम को 200 विभाजन में विभाजित किया गया है।

df.repartition(500): डेटा को 200 विभाजन से नए 500 विभाजन में बदल दिया जाएगा।

तराजू : डेटा को मौजूदा विभाजन की संख्या में फेरबदल करें।

df.coalesce(5): डेटा को शेष 195 विभाजन से 5 मौजूदा विभाजन में बदल दिया जाएगा।


4

मैं जस्टिन और पावर के जवाब में जोड़ना चाहूंगा कि -

repartitionमौजूदा विभाजन को अनदेखा करेगा और नए बनाएगा। तो आप इसका उपयोग डेटा तिरछा को ठीक करने के लिए कर सकते हैं। आप वितरण को परिभाषित करने के लिए विभाजन कुंजियों का उल्लेख कर सकते हैं। डेटा तिरछा 'बिग डेटा' समस्या स्थान में सबसे बड़ी समस्याओं में से एक है।

coalesceमौजूदा विभाजन के साथ काम करेंगे और उनमें से एक सबसेट को फेरबदल करेंगे। यह डेटा तिरछा को ठीक नहीं कर सकता repartitionहै। इसलिए भले ही यह कम खर्चीला हो लेकिन यह आपकी जरूरत की चीज नहीं हो सकती है।


3

सभी महान उत्तरों के लिए, मैं जोड़ना चाहूंगा कि repartitionडेटा समानांतर का लाभ उठाने के लिए सबसे अच्छा विकल्प है। जबकि coalesceएक सस्ते विभाजन को कम करने का विकल्प देता है और यह बहुत उपयोगी है जब HDFS या कुछ अन्य सिंक करने के लिए डेटा लेखन बड़ा राईट का लाभ लेने के।

पूरा फायदा पाने के लिए मैंने लकवे के प्रारूप में डेटा लिखते समय इसे उपयोगी पाया है।


2

उन लोगों के लिए, जिनके पास आउटपुट के रूप में PySpark (AWS EMR) से एक एकल सीएसवी फ़ाइल बनाने के मुद्दे थे और इसे s3 पर सहेजना, पुन: उपयोग करने में मदद मिली। इसका कारण, सहवास एक पूर्ण फेरबदल नहीं कर सकता, लेकिन पुनरावृत्ति कर सकता है। अनिवार्य रूप से, आप पुन: विभाजन का उपयोग करके विभाजन की संख्या को बढ़ा या घटा सकते हैं, लेकिन केवल सह-विभाजन का उपयोग करके विभाजन की संख्या (लेकिन 1 नहीं) को घटा सकते हैं। यहां वह कोई भी व्यक्ति है जो AWS EMR से s3 तक csv लिखने का प्रयास कर रहा है:

df.repartition(1).write.format('csv')\
.option("path", "s3a://my.bucket.name/location")\
.save(header = 'true')

0

एक सरल तरीके से COALESCE: - केवल विभाजन की संख्या को कम करने के लिए है, डेटा का फेरबदल नहीं है, यह सिर्फ विभाजन को संपीड़ित करता है।

रिपोर्ट: - विभाजन की संख्या में वृद्धि और कमी दोनों के लिए है, लेकिन फेरबदल होता है

उदाहरण:-

val rdd = sc.textFile("path",7)
rdd.repartition(10)
rdd.repartition(2)

दोनों ठीक काम करते हैं

लेकिन हम आम तौर पर इस दो चीजों के लिए जाते हैं जब हमें एक क्लस्टर में आउटपुट देखने की आवश्यकता होती है, तो हम इसके साथ जाते हैं।


9
कोयले के साथ आंकड़ों की आवाजाही होगी।
sun_dare

0

लेकिन साथ ही आपको यह भी सुनिश्चित करना चाहिए कि, जो डेटा कॉल्सस नोड्स आ रहा है, उसे अत्यधिक कॉन्फ़िगर किया जाना चाहिए, यदि आप विशाल डेटा के साथ काम कर रहे हैं। क्योंकि सभी डेटा उन नोड्स में लोड किए जाएंगे, जो मेमोरी अपवाद का नेतृत्व कर सकते हैं। हालांकि पुनर्मूल्यांकन महंगा है, मैं इसका उपयोग करना पसंद करता हूं। चूंकि यह फेरबदल करता है और डेटा को समान रूप से वितरित करता है।

मोटे और प्रत्यावर्तन के बीच चयन करने के लिए बुद्धिमान बनें।


0

repartitionएल्गोरिथ्म डेटा की पूरी फेरबदल करता है और डेटा के बराबर आकार के विभाजन पैदा करता है। coalesceएक पूर्ण फेरबदल से बचने के लिए मौजूदा विभाजन को जोड़ती है।

Coalesce बहुत सारे विभाजन के साथ RDD लेने और कम विभाजन के साथ अंतिम RDD का निर्माण करने के लिए किसी एक कार्यकर्ता नोड पर विभाजनों के संयोजन के लिए अच्छी तरह से काम करता है।

Repartitionआपके RDD में आपके द्वारा अनुरोध किए गए विभाजन की अंतिम संख्या का उत्पादन करने के लिए डेटा में फेरबदल किया जाएगा। DataFrames का विभाजन निम्न स्तर के कार्यान्वयन विवरण की तरह लगता है जिसे फ्रेमवर्क द्वारा प्रबंधित किया जाना चाहिए, लेकिन ऐसा नहीं है। जब बड़े डेटाफ़्रेम को छोटे लोगों में फ़िल्टर किया जाता है, तो आपको डेटा को लगभग हमेशा पुनर्प्रतिष्ठित करना चाहिए। आप शायद बड़े डेटाफ़्रेम को छोटे लोगों में फ़िल्टर कर रहे होंगे, इसलिए उन्हें पुन: उपयोग करने की आदत डालें।

यदि आप और भी अधिक विवरण चाहते हैं तो इस ब्लॉग पोस्ट को पढ़ें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.