2016-08-24 13 views
6

में कक्षाओं के मामले में लोडिंग लकड़ी की छत फ़ाइलों का प्रदर्शन मैं स्पार्क में लकड़ी की छत फ़ाइलों को लोड करने के विभिन्न तरीकों के प्रदर्शन का आकलन कर रहा हूं और अंतर चौंकाने वाला है।स्पार्क

प्रकार के

हमारे लकड़ी फ़ाइलों में, हम नेस्ट है मामले कक्षाएं:

case class C(/* a dozen of attributes*/) 
case class B(/* a dozen of attributes*/, cs: Seq[C]) 
case class A(/* a dozen of attributes*/, bs: Seq[B]) 

यह कुछ समय लगता है उन्हें लकड़ी फ़ाइलों से लोड करने के लिए। इसलिए मैंने पैराक्वेट फ़ाइलों से केस क्लास लोड करने और स्पार्क 1.6 और 2.0 का उपयोग करके फ़ील्ड को एकत्र करने के विभिन्न तरीकों का बेंचमार्क किया है। के बाद से Dataframe अब Dataset[Row] का एक मात्र अन्य नाम है,

val df: DataFrame = sqlContext.read.parquet("path/to/file.gz.parquet").persist() 
df.count() 

// Spark 1.6 

// Play Json 
// 63.169s 
df.toJSON.flatMap(s => Try(Json.parse(s).as[A]).toOption) 
     .map(_.fieldToSum).sum() 

// Direct access to field using Spark Row 
// 2.811s 
df.map(row => row.getAs[Long]("fieldToSum")).sum() 

// Some small library we developed that access fields using Spark Row 
// 10.401s 
df.toRDD[A].map(_.fieldToSum).sum() 

// Dataframe hybrid SQL API 
// 0.239s 
df.agg(sum("fieldToSum")).collect().head.getAs[Long](0) 

// Dataset with RDD-style code 
// 34.223s 
df.as[A].map(_.fieldToSum).reduce(_ + _) 

// Dataset with column selection 
// 0.176s 
df.as[A].select($"fieldToSum".as[Long]).reduce(_ + _) 


// Spark 2.0 

// Performance is similar except for: 

// Direct access to field using Spark Row 
// 23.168s 
df.map(row => row.getAs[Long]("fieldToSum")).reduce(_ + _) 

// Some small library we developed that access fields using Spark Row 
// 32.898s 
f1DF.toRDD[A].map(_.fieldToSum).sum() 

मुझे समझ में क्यों स्पार्क पंक्ति का उपयोग कर विधियों में से प्रदर्शन जब 2.0 स्पार्क के उन्नयन अपमानित किया जाता है:

यहाँ बेंचमार्क मैंने किया था का सार है। इंटरफेस को एकीकृत करने की लागत है, मुझे लगता है। जब RDD शैली कोडिंग (map और flatMap रों) जब Dataframe तरह Dataset का उपयोग कर SQL जैसी डीएसएल के साथ से भी बदतर है का उपयोग करते हुए प्रदर्शन:

दूसरी ओर, मैं काफी निराश है कि Dataset का वादा निभाया नहीं है कर रहा हूँ ।

असल में, अच्छा प्रदर्शन करने के लिए, हमें प्रकार की सुरक्षा छोड़नी होगी।

  1. Dataframe के रूप में इस्तेमाल RDD और Dataset के रूप में इस्तेमाल Dataset के बीच इस तरह के अंतर की वजह क्या है?

  2. क्या आरडीडी-शैली कोडिंग और एसक्यूएल-शैली कोडिंग प्रदर्शन को समतुल्य करने के लिए Dataset में एन्कोडिंग प्रदर्शन में सुधार करने का कोई तरीका है? डेटा इंजीनियरिंग के लिए, आरडीडी-शैली कोडिंग के लिए यह बहुत साफ है।

  3. इसके अलावा, एसक्यूएल-जैसे डीएसएल के साथ काम करने के लिए हमारे डेटा मॉडल को फ़्लैट करना होगा और नेस्टेड केस क्लासेस का उपयोग नहीं करना होगा। क्या मैं सही हूं कि अच्छा प्रदर्शन केवल फ्लैट डेटा मॉडल के साथ हासिल किया जाता है?

उत्तर

2

क्या डेटासेट के बीच इस तरह के अंतर की वजह इस्तेमाल के रूप में RDD और डेटासेट Dataframe रूप में इस्तेमाल किया है?

कुछ अंतर्दृष्टि प्राप्त करने के लिए स्पार्क एसक्यूएल द्वारा उपयोग किए जाने वाले अनुकूलन के बारे में सोचें। जहां तक ​​मुझे पता है सादा RDD से अधिक सुधार के तीन प्रकार हूँ:

  • कार्य योजना लागू करके अनुकूलन (अनुमानों और चयन पुशडाउन, निरंतर तह),
  • देशी (बंद ढेर) स्मृति के उपयोग और कुशल स्तंभ कैशिंग प्रारूप ,
  • कोड जनरेशन।

अब समस्या यह है कि इन सभी तकनीकों को एसक्यूएल जैसे प्रतिबंधित प्रोग्रामिंग मॉडल के बाहर उपयोगी नहीं है।

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

अंत में sun.misc.Unsafe प्रदर्शन में सुधार करने का एक शानदार तरीका है लेकिन यह मुफ्त में नहीं आता है। यहां पर बहुत लाभ है जबकि एन्कोडिंग और डिकोडिंग का एक महत्वपूर्ण ओवरहेड भी है।

एसक्यूएल-जैसे डीएसएल के साथ काम करने के लिए हमारे डेटा मॉडल को फ़्लैट करना होगा और नेस्टेड केस क्लास का उपयोग नहीं करना होगा।

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

प्रदर्शन जब 2.0 स्पार्क के उन्नयन अपमानित किया जाता है, के बाद से Dataframe अब डेटासेट [पंक्ति] की एक मात्र उर्फ ​​है। मुझे लगता है कि इंटरफेस को एकीकृत करने की लागत है।

हालांकि कुछ प्रदर्शन प्रतिगमन किया गया है, कोड के इन दो टुकड़े बराबर नहीं हैं। 2.0.0+ DataFrame.map में इसके 1.x समकक्ष की तुलना में अलग हस्ताक्षर हैं। आप इन दो तुलनीय आप में बदलने चाहिए बनाना चाहते हैं RDD पहले: स्पार्क 1.x और 2. x में `के बीच Dataframe.map` इंटरफेस अंतर दिखाई दे

df.rdd.map(row => row.getAs[Long]("fieldToSum")).reduce(_ + _) 
+0

मैं स्पार्क इंटरफेस में पर्याप्त delved नहीं था फिर भी, 'df.rdd.map (row => row.getAs [long] ("fieldToSum"))। (_ + _) 'और' df.map (row => row.getAs [long] ("fieldToSum को कम करें) "))। कम करें (_ + _) 'मोटे तौर पर एक ही प्रदर्शन है। प्रदर्शन को बनाए रखने के लिए पुराने तंत्र पर वापस जाने का कोई तरीका नहीं है? – jrjd

+0

कोई भी जो मुझे पता है लेकिन निष्पक्ष होने के लिए मुझे यकीन नहीं है कि इस विशेष मामले में अपराधी क्या है और मैं वास्तव में वास्तव में इस तरह के अंतर को पुन: उत्पन्न नहीं कर सकता। हालांकि यह dev सूची के लिए अग्रेषित लायक हो सकता है। – zero323