स्पार्क: यूडीएफ को कई बार निष्पादित किया गया


9

मेरे पास निम्नलिखित कोड के साथ एक डेटाफ्रेम है:

def test(lat: Double, lon: Double) = {
  println(s"testing ${lat / lon}")
  Map("one" -> "one", "two" -> "two")
}

val testUDF = udf(test _)

df.withColumn("test", testUDF(col("lat"), col("lon")))
  .withColumn("test1", col("test.one"))
  .withColumn("test2", col("test.two"))

अब लॉग की जांच करते हुए, मुझे पता चला कि प्रत्येक पंक्ति के लिए यूडीएफ को 3 बार निष्पादित किया जाता है। यदि मैं "test3" को "test.three" कॉलम से जोड़ता हूं तो UDF को एक बार फिर निष्पादित किया जाता है।

क्या कोई मुझे समझा सकता है क्यों?

क्या इसे ठीक से टाला जा सकता है ("परीक्षण" के बाद डेटाफ़्रेम को शामिल किए बिना, भले ही यह काम करता हो)?


क्या मतलब? आप परीक्षण फ़ंक्शन को तीन बार कॉल कर रहे हैं। इसलिए इसे तीन बार अंजाम दिया जा रहा है। यकीन नहीं होता कि आप इसे यूडीएफ क्यों बना रहे हैं। क्यों न केवल मानचित्र को एक घाटी बनाएं?
15:46 बजे user4601931

यह चिंगारी के व्यवहार को दिखाने के लिए सिर्फ एक उदाहरण है। मेरे लिए "परीक्षण" एक नया स्तंभ है जिसमें एक संरचना शामिल है, फिर संरचना के किसी भी हिस्से तक पहुंचना यूडीएफ को फिर से निष्पादित नहीं करना चाहिए। मैं कैसे गलत हूं?
रोलिंटोकोर 16

मैंने स्कीमा को प्रिंट करने की कोशिश की, "टेस्ट" का डेटाटाइप है, Mapस्ट्रक्चर नहीं। अब एक मैप वापस करने के बजाय, यदि UDF टेस्ट (एक स्ट्रिंग, दो: स्ट्रिंग) की तरह एक केस क्लास लौटाता है, तो testवास्तव में एक स्ट्रक्चर्स है, लेकिन हमेशा यूडीएफ के कई निष्पादन होते हैं।
रोलिंटोकोर


कैशिंग को इस उत्तर के अनुसार काम करना चाहिए: stackoverflow.com/a/40962714/1138523
राफेल रोथ

जवाबों:


5

यदि आप एक udf के लिए कई कॉल से बचना चाहते हैं (जो कि विशेष रूप से उपयोगी है अगर udf आपके काम में अड़चन है) तो आप इसे निम्नानुसार कर सकते हैं:

val testUDF = udf(test _).asNondeterministic()

मूल रूप से आप स्पार्क को बताते हैं कि आपका कार्य निर्धारक नहीं है और अब स्पार्क यह सुनिश्चित करता है कि इसे केवल एक बार कहा जाए क्योंकि इसे कई बार कॉल करना सुरक्षित नहीं है (प्रत्येक कॉल संभवतः अलग परिणाम लौटा सकती है)।

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


अच्छा! यह उत्तर यहां भी दिया गया है: stackoverflow.com/questions/40320563/…
राफेल रोथ

मेरे मामले में, asNondeterministicकेवल एक बार निष्पादित करने के लिए यूडीएफ को मजबूर करता है। explode(array(myUdf($"id")))समाधान के साथ , यह अभी भी दो बार निष्पादित हो जाता है।
रोलिंटोकोर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.