2015-10-23 10 views
10

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

ऐसा करने के लिए, मैंने स्काला में एक जार फ़ाइल बनाई है जो स्पार्कएसक्यूएल लाइब्रेरी का उपयोग डेटाबेस से पूछताछ करने और डेटाफ्रेम को प्राप्त करने के लिए करता है। मैं एक और जेवीएम बनाने के बिना इन कार्यों को आर में कॉल करने में सक्षम होना चाहता था, क्योंकि स्पार्क आर में पहले से ही एक जेवीएम पर चलता है। हालांकि, जेवीएम स्पार्क का उपयोग स्पार्कआर एपीआई में नहीं दिखता है। इसे सुलभ बनाने और जावा विधियों को कॉल करने योग्य बनाने के लिए, मैंने स्पार्कआर पैकेज में "बैकएंड.आर", "जेनेरिक.आर", "डेटाफ्रेम.आर", और "नेमस्पेस" संशोधित किया और पैकेज का पुनर्निर्माण किया:

"बैकएंड में .R callJMethod "और" createJObject "औपचारिक तरीके:

setMethod("callJMethod", signature(objId="jobj", methodName="character"), function(objId, methodName, ...) { 
    stopifnot(class(objId) == "jobj") 
    if (!isValidJobj(objId)) { 
    stop("Invalid jobj ", objId$id, 
     ". If SparkR was restarted, Spark operations need to be re-executed.") 
    } 
    invokeJava(isStatic = FALSE, objId$id, methodName, ...) 
}) 


    setMethod("newJObject", signature(className="character"), function(className, ...) { 
    invokeJava(isStatic = TRUE, className, methodName = "<init>", ...) 
}) 

मैं संशोधित" "मैं बनाया" generics.R "ये फ़ंक्शन भी शामिल करने के लिए:

#' @rdname callJMethod 
#' @export 
setGeneric("callJMethod", function(objId, methodName, ...) { standardGeneric("callJMethod")}) 

#' @rdname newJobject 
#' @export 
setGeneric("newJObject", function(className, ...) {standardGeneric("newJObject")}) 

तो मैं करने के लिए इन कार्यों के लिए निर्यात को जोड़ा NAMESPACE फ़ाइल:

export("cacheTable", 
    "clearCache", 
    "createDataFrame", 
    "createExternalTable", 
    "dropTempTable", 
    "jsonFile", 
    "loadDF", 
    "parquetFile", 
    "read.df", 
    "sql", 
    "table", 
    "tableNames", 
    "tables", 
    "uncacheTable", 
    "callJMethod", 
    "newJObject") 

इससे मुझे एक नया जेवीएम शुरू किए बिना स्कैला कार्यों को कॉल करने की अनुमति मिली।

स्केल विधियों को मैंने वापस लौटाया डेटाफ्रेम, जो लौटने पर आर में "जॉबज" हैं, लेकिन स्पार्कआर डेटाफ्रेम एक पर्यावरण + नौकरी है। इन जॉबज डेटाफ्रेम को स्पार्कआर डेटाफ्रेम में बदलने के लिए, मैंने डेटाफ्रेम (आर) में डेटाफ्रेम() फ़ंक्शन का उपयोग किया, जिसे मैंने ऊपर दिए गए चरणों के बाद भी सुलभ बनाया।

मैं तब डेटाफ्रेम तक पहुंचने में सक्षम था जिसे मैंने आर से स्कैला में "बनाया" और उस डेटाफ्रेम पर स्पार्कआर के सभी कार्यों का उपयोग किया। मैं सोच रहा था कि क्या ऐसी क्रॉस-भाषा लाइब्रेरी बनाने का कोई बेहतर तरीका है, या यदि कोई कारण है कि स्पार्क जेवीएम सार्वजनिक नहीं होना चाहिए?

उत्तर

4

किसी भी कारण स्पार्क जेवीएम सार्वजनिक नहीं होना चाहिए?

शायद एक से अधिक। स्पार्क डेवलपर्स एक स्थिर सार्वजनिक एपीआई प्रदान करने के लिए गंभीर प्रयास करते हैं। कार्यान्वयन के कम विवरण, जिस तरह से अतिथि भाषाएं JVM के साथ संवाद करती हैं, वे अनुबंध का हिस्सा नहीं हैं। उपयोगकर्ताओं पर किसी भी नकारात्मक प्रभाव के बिना इसे पूरी तरह से फिर से लिखा जा सकता है। यदि आप इसका उपयोग करने का निर्णय लेते हैं और पीछे की असंगत परिवर्तन हैं जो आप स्वयं हैं।

आंतरिक निजी रखने से सॉफ्टवेयर को बनाए रखने और समर्थन करने के प्रयास कम हो जाते हैं। आप बस उन सभी संभावित तरीकों से परेशान नहीं हैं जिनमें उपयोगकर्ता इनका दुरुपयोग कर सकता है।

एक बेहतर तरीका इस तरह के एक पार भाषा पुस्तकालय बनाने के लिए

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

  • स्टार्टर्स आर के लिए केवल एक कमजोर पहुंच नियंत्रण तंत्र प्रदान करता है। यदि एपीआई का कोई भी हिस्सा आंतरिक है तो आप इसे एक्सेस करने के लिए हमेशा ::: फ़ंक्शन का उपयोग कर सकते हैं।के रूप में स्मार्ट लोगों का कहना है:

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

    लेकिन यह सुनिश्चित करने के लिए एक बात स्पार्क स्रोत को संशोधित करने से काफी बेहतर है। बोनस के रूप में यह स्पष्ट रूप से आपके कोड के कुछ हिस्सों को चिह्नित करता है जो विशेष रूप से नाजुक रूप से अस्थिर होते हैं।

  • अगर सभी आप चाहते हैं DataFrames सरल बात कच्चे एसक्यूएल उपयोग करने के लिए है बनाने के लिए है। यह साफ, पोर्टेबल है, कोई संकलन, पैकेजिंग और बस काम करता है। मान लिया जाये कि आप नीचे q

    CREATE TEMPORARY TABLE foo 
    USING org.apache.spark.sql.jdbc 
    OPTIONS (
        url "jdbc:postgresql://localhost/test", 
        dbtable "public.foo", 
        driver "org.postgresql.Driver" 
    ) 
    

    नामित चर में संग्रहीत यह अनुसंधान में इस्तेमाल किया जा सकता है जैसे स्ट्रिंग:

    sql(sqlContext, q) 
    fooDF <- sql(sqlContext, "SELECT * FROM foo") 
    

    पायथन:

    sqlContext.sql(q) 
    fooDF = sqlContext.sql("SELECT * FROM foo") 
    

    स्काला:

    sqlContext.sql(q) 
    val fooDF = sqlContext.sql("SELECT * FROM foo") 
    

    या सीधे स्पार्क एसक्यूएल में।

  • अंत में आप निरंतर और समर्थित क्रॉस-प्लेटफ़ॉर्म पहुंच के लिए Spark Data Sources API का उपयोग कर सकते हैं।

इन तीनों में से मैं कच्चे एसक्यूएल को पसंद करूंगा, इसके बाद जटिल मामलों के लिए डेटा स्रोत एपीआई और अंतिम उपाय के रूप में आंतरिक छोड़ दें।

संपादित(2016/08/04):

आप JVM करने के लिए निम्न स्तर का उपयोग कर सकते में रुचि रखते हैं वहाँ अपेक्षाकृत नया पैकेज rstudio/sparkapi जो आंतरिक SparkR RPC प्रोटोकॉल को उजागर करता है। भविष्यवाणी करना मुश्किल है कि यह कैसे विकसित होगा, इसलिए इसे अपने जोखिम पर उपयोग करें।

+0

लेकिन क्या डेटा स्टोर को स्टोर किए बिना इसे फिर से पढ़ने के बिना आर और स्कैला में डेटाफ्रेम साझा करने का कोई अच्छा तरीका है? जब तक मुझे कुछ समाधान नहीं मिल रहा है 2 और 3 दोनों को इसकी आवश्यकता होती है। – shj

+0

मुझे बिल्कुल यकीन नहीं है कि आप क्या चाहते हैं। स्पार्क प्रति जेवीएम के कई संदर्भों का समर्थन नहीं करता है (देखें [स्पार्क -2243] (https://issues.apache.org/jira/browse/SPARK-2243)) और न ही संदर्भों के बीच आरडीडी साझा करना। तो सभी तीनों को किसी प्रकार के भंडारण से डेटा पढ़ने की आवश्यकता होती है। वहां कुछ विकल्प हैं [स्पार्क-जॉब्सवर] (https://github.com/spark-jobserver/spark-jobserver), ["साझा" आरडीडी] (https://ignite.apache.org/features/igniterdd। एचटीएमएल) Ignite के शीर्ष पर या [Tachyon] (http://tachyon-project.org/) का उपयोग स्मृति मेमोरी स्टोरेज परत के रूप में करते हैं जो इस समस्या को हल करने का प्रयास करता है लेकिन जेवीएम को सरल करने से आपको कहीं भी नहीं मिल जाएगा। – zero323

+0

सरल एसक्यूएल प्रश्नों के लिए आप शायद बुइट-इन [थ्रिफ्ट सर्वर] (http://spark.apache.org/docs/latest/sql-programming-guide.html#running-the-thrift-jdbcodbc-server) का उपयोग कर सकते हैं। – zero323

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

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