2017-12-22 85 views
7

मैं जब .select() का उपयोग कर एक आश्चर्य की बात व्यवहार में भाग:वास्तव में क्या करता है। चयन करें() करें?

>>> my_df.show() 
+---+---+---+ 
| a| b| c| 
+---+---+---+ 
| 1| 3| 5| 
| 2| 4| 6| 
+---+---+---+ 

>>> a_c = s_df.select(col("a"), col("c")) # removing column b 
>>> a_c.show() 
+---+---+ 
| a| c| 
+---+---+ 
| 1| 5| 
| 2| 6| 
+---+---+ 

>>> a_c.filter(col("b") == 3).show() # I can still filter on "b"! 
+---+---+ 
| a| c| 
+---+---+ 
| 1| 5| 
+---+---+ 

यह व्यवहार मिला मेरी सोच ... मेरे निम्नलिखित बातों पर सही हैं?

डेटाफ्रेम केवल विचार हैं, एक साधारण डेटाफ्रेम स्वयं का एक दृश्य है। मेरे मामले में a_c सिर्फ my_df में एक दृश्य है।

जब मैंने a_c बनाया कोई नया डेटा नहीं बनाया गया था, a_c केवल उसी डेटा पर इंगित कर रहा है my_df इंगित कर रहा है।

यदि अतिरिक्त जानकारी है जो प्रासंगिक है, तो कृपया जोड़ें!

उत्तर

6

यह स्पार्क की आलसी प्रकृति के कारण हो रहा है। फ़िल्टर को धक्का देने के लिए यह "स्मार्ट" पर्याप्त है ताकि यह निचले स्तर पर हो - फिल्टर * से पहले। इसलिए, चूंकि यह सब निष्पादन के stage के भीतर होता है और अभी भी हल किया जा सकता है। वास्तव में आप explain में देख सकते हैं:

== Physical Plan == 
*Project [a#0, c#2] 
+- *Filter (b#1 = 3) <---Filter before Project 
    +- LocalTableScan [A#0, B#1, C#2] 

आप एक फेरबदल और नए मंच, है, हालांकि मजबूर कर सकते हैं तो अपने फिल्टर असफल देखते हैं। संकलन समय पर भी इसे पकड़ना। यहाँ एक उदाहरण है:

a_c.groupBy("a","c").count.filter(col("b") === 3) 

* वहाँ भी एक प्रक्षेपण छंटाई कि डेटाबेस परतों के नीचे चयन धक्का अगर यह पता चलता है कि यह किसी भी बिंदु पर स्तंभ की जरूरत नहीं है है। हालांकि मुझे विश्वास है कि फिल्टर इसे "ज़रूरत" के कारण बन जाएगा और छेड़छाड़ नहीं करेगा ... लेकिन मैंने इसका परीक्षण नहीं किया।

1

आइए हम स्पार्क अंतर्निहित के बारे में कुछ मूलभूत बातें शुरू करें। इससे आपकी समझ आसान हो जाएगी। आरडीडी: स्पार्क कोर अंतर्निहित आरडीडी नामक डेटा संरचना है, जो आलसी मूल्यांकन है। आलसी मूल्यांकन से हमारा मतलब है कि आरडीडी गणना तब होती है जब कार्रवाई (जैसे आरडीडी में गिनती कॉल करना या डेटासेट में दिखाएं)।

डेटासेट या डेटाफ्रेम (कौन सा डेटासेट [पंक्ति]) कोर पर आरडीडी का भी उपयोग करता है।

इसका मतलब है कि प्रत्येक परिवर्तन (फ़िल्टर की तरह) केवल तभी महसूस किया जाएगा जब कार्रवाई ट्रिगर (शो) हो।

तो आपका प्रश्न "जब मैंने a_c बनाया तो कोई नया डेटा नहीं बनाया गया था, a_c बस उसी डेटा पर इंगित कर रहा है my_df इंगित कर रहा है।"
चूंकि कोई डेटा नहीं मिला है। हमें इसे स्मृति में लाने के लिए इसका एहसास होना है। आपका फ़िल्टर प्रारंभिक डेटाफ्रेम पर काम करता है। अपना a_c.filter(col("b") == 3).show() एक रन टाइम अपवाद फेंकने का एकमात्र तरीका डेटाफ्रेम.cache का उपयोग करके अपने मध्यवर्ती डेटाफ्रेम को कैश करना है। तो स्पार्क "मुख्य" org.apache.spark.sql.AnalysisException फेंक देगा: कॉलम नाम जैसे हल नहीं कर सकता।

val a_c = s_df.select(col("a"), col("c")).cache 
     a_c.filter(col("b") == 3).show() 

तो चिंगारी फेंक होगा "मुख्य" org.apache.spark.sql.AnalysisException: नहीं कर पा रहे संकल्प स्तंभ नाम।

+0

चरणों समझा बिना के रूप में @Chris एच –

+0

मुझे लगता है कि ने सुझाव दिया जवाब अद्यतन इस व्याख्या क्या वास्तव में हो रहा है के मांस का अभाव है –

+0

@ JustinPihony- मुझे लगता है कि मंच इस मामले में पर्याप्त तर्क नहीं है। –

संबंधित मुद्दे