मैं स्पार्क 3.0.1 के साथ काम कर रहा हूं और मेरी विभाजित तालिका s3 में संग्रहीत है। कृपया इस मुद्दे का विवरण यहां देखें।

तालिका बनाएं

Create table root_table_test_spark_3_0_1 (
    id string,
    name string
)
USING PARQUET
PARTITIONED BY (id)
LOCATION  's3a://MY_BUCKET_NAME/'

कोड जो दूसरे रन पर NullPointerException पैदा कर रहा है

Seq(MinimalObject("id_1", "name_1"), MinimalObject("id_2", "name_2"))
      .toDS()
      .write
      .partitionBy("id")
      .mode(SaveMode.Append)
      .saveAsTable("root_table_test_spark_3_0_1")

जब हाइव मेटास्टोर खाली होता है तो सब कुछ ठीक होता है लेकिन समस्या तब हो रही है जब स्पार्क getCustomPartitionLocations को InsertIntoHadoopFsRelationCommand चरण में करने का प्रयास कर रहा है। (उदाहरण के लिए दूसरे रन पर)

वास्तव में यह नीचे दी गई विधि को कॉल करता है: से (org.apache.hadoop.fs.Path)

/** Adds a suffix to the final name in the path.*/
public Path suffix(String suffix) {
    return new Path(getParent(), getName()+suffix);
}

लेकिन जब हम रूट पर होंगे तो getParent() शून्य वापस आ जाएगा, जिसके परिणामस्वरूप NullPointerException होगा। इस समय मैं सोच रहा हूं कि एकमात्र विकल्प इस विधि को कुछ ऐसा करने के लिए ओवरराइड करना है:

/** Adds a suffix to the final name in the path.*/
public Path suffix(String suffix) {
    return (isRoot()) ? new Path(uri.getScheme(), uri.getAuthority(), suffix) : new Path(getParent(), getName()+suffix);
}

किसी को भी समस्या हो रही है जब LOCATION स्पार्क हाइव टेबल रूट स्तर पर है? कोई उपाय? क्या कोई ज्ञात समस्या खोली गई है?

मेरा रनटाइम मुझे पथ वर्ग को ओवरराइड करने और suffix विधि को ठीक करने की अनुमति नहीं देता है और मैं अपने डेटा को बाल्टी की जड़ से नहीं ले जा सकता क्योंकि यह 2 साल से मौजूद है।

समस्या इसलिए होती है क्योंकि मैं स्पार्क 2.1.0 से स्पार्क 3.0.1 में माइग्रेट कर रहा हूं और कस्टम विभाजन की जांच करने वाला व्यवहार स्पार्क 2.2.0 (https://github.com/apache/spark/pull/16460)

यह पूरा संदर्भ समस्या को समझने में मदद करता है लेकिन मूल रूप से आप इसे आसानी से पुन: पेश कर सकते हैं

val path: Path = new Path("s3a://MY_BUCKET_NAME/")
println(path.suffix("/id=id"))

एफवाईआई। हडूप-सामान्य संस्करण 2.7.4 है और कृपया यहां पूर्ण स्टैकट्रेस ढूंढें

NullPointerException
at org.apache.hadoop.fs.Path.<init>(Path.java:104)
    at org.apache.hadoop.fs.Path.<init>(Path.java:93)
    at org.apache.hadoop.fs.Path.suffix(Path.java:361)
    at org.apache.spark.sql.execution.datasources.InsertIntoHadoopFsRelationCommand.$anonfun$getCustomPartitionLocations$1(InsertIntoHadoopFsRelationCommand.scala:262)
    at scala.collection.TraversableLike.$anonfun$flatMap$1(TraversableLike.scala:245)
    at scala.collection.mutable.ResizableArray.foreach(ResizableArray.scala:62)
    at scala.collection.mutable.ResizableArray.foreach$(ResizableArray.scala:55)
    at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:49)
    at scala.collection.TraversableLike.flatMap(TraversableLike.scala:245)
    at scala.collection.TraversableLike.flatMap$(TraversableLike.scala:242)
    at scala.collection.AbstractTraversable.flatMap(Traversable.scala:108)
    at org.apache.spark.sql.execution.datasources.InsertIntoHadoopFsRelationCommand.getCustomPartitionLocations(InsertIntoHadoopFsRelationCommand.scala:260)
    at org.apache.spark.sql.execution.datasources.InsertIntoHadoopFsRelationCommand.run(InsertIntoHadoopFsRelationCommand.scala:107)
    at org.apache.spark.sql.execution.datasources.DataSource.writeAndRead(DataSource.scala:575)
    at org.apache.spark.sql.execution.command.CreateDataSourceTableAsSelectCommand.saveDataIntoTable(createDataSourceTables.scala:218)
    at org.apache.spark.sql.execution.command.CreateDataSourceTableAsSelectCommand.run(createDataSourceTables.scala:166)

धन्यवाद

1
Michael 10 अक्टूबर 2020, 00:39

1 उत्तर

सबसे बढ़िया उत्तर

ऐसा लगता है कि स्पार्क कोड Path.suffix("something) को कॉल करता है और क्योंकि रूट पथ में कोई माता-पिता नहीं है, एक एनपीई ट्रिगर होता है

लॉन्ग टर्म फिक्स

  1. HADOOP के खिलाफ मुद्दों.apache.org पर जिरा फाइल करें; रूट पथ पर कॉल करने पर ठीक से डाउनग्रेड करने के लिए फिक्स प्रत्यय () के लिए परीक्षण के साथ एक पैच प्रदान करें। सभी के लिए सर्वश्रेष्ठ
  2. किसी तालिका के गंतव्य के रूप में रूट पथ का उपयोग न करें।
  3. ये दोनों करें

विकल्प # 2 को अन्य आश्चर्यों से बचना चाहिए कि टेबल कैसे बनाए जाते हैं/प्रतिबद्ध आदि ... कुछ कोड विफल हो सकते हैं क्योंकि पथ की जड़ को हटाने का प्रयास (यहां s3a: //some-bucket") नहीं हटाएगा जड़, होगा?

अलग तरीके से रखें: रूट निर्देशिकाओं में हर जगह "विषम" शब्दार्थ होते हैं; अधिकांश समय आप इसे स्थानीय एफएस पर नोटिस नहीं करते हैं क्योंकि आप कभी भी काम के गंतव्य के रूप में उपयोग करने की कोशिश नहीं करते हैं, आश्चर्यचकित हो जाते हैं कि आरएम-आरएफ / आरएम-आरएफ / सबडिर आदि से अलग है। स्पार्क, हाइव इत्यादि। काम के गंतव्य के रूप में / का उपयोग करने के लिए कभी नहीं लिखा गया था, इसलिए आपको विफलताएं देखने को मिलती हैं।

1
stevel 14 अक्टूबर 2020, 11:58