簡體   English   中英

如何在 Spark 中更新幾條記錄

[英]How to update few records in Spark

我在 Scala 中有以下用於 spark 的程序:

val dfA = sqlContext.sql("select * from employees where id in ('Emp1', 'Emp2')" )
val dfB = sqlContext.sql("select * from employees where id not in ('Emp1', 'Emp2')" )
val dfN = dfA.withColumn("department", lit("Finance"))
val dfFinal = dfN.unionAll(dfB)
dfFinal.registerTempTable("intermediate_result")

dfA.unpersist
dfB.unpersist
dfN.unpersist
dfFinal.unpersist

val dfTmp = sqlContext.sql("select * from intermediate_result")
dfTmp.write.mode("overwrite").format("parquet").saveAsTable("employees")
dfTmp.unpersist

當我嘗試保存它時,出現以下錯誤:

org.apache.spark.sql.AnalysisException:無法覆蓋正在讀取的表employees 。; 在 org.apache.spark.sql.execution.datasources.PreWriteCheck.failAnalysis(rules.scala:106) 在 org.apache.spark.sql.execution.datasources.PreWriteCheck$$anonfun$apply$3.apply(rules.scala: 182)在 org.apache.spark.sql.execution.datasources.PreWriteCheck$$anonfun$apply$3.apply(rules.scala:109) 在 org.apache.spark.sql.catalyst.trees.TreeNode.foreach(TreeNode. scala:111) 在 org.apache.spark.sql.execution.datasources.PreWriteCheck.apply(rules.scala:109) 在 org.apache.spark.sql.execution.datasources.PreWriteCheck.apply(rules.scala:105)在 org.apache.spark.sql.catalyst.analysis.CheckAnalysis$$anonfun$checkAnalysis$2.apply(CheckAnalysis.scala:218) 在 org.apache.spark.sql.catalyst.analysis.CheckAnalysis$$anonfun$checkAnalysis$2。在 scala.collection.immutable.List.foreach(List.scala:318) 處應用(CheckAnalysis.scala:218)

我的問題是:

  1. 我的方法是否正確更改兩名員工的部門
  2. 為什么我在發布 DataFrame 時會收到此錯誤

我的方法是否正確,以更改兩名員工的部門

它不是。 只是為了重復在Stack Overflow上多次說過的話-Apache Spark不是數據庫 它不適用於細粒度的更新。 如果您的項目需要這樣的操作,請使用Hadoop上眾多數據庫之一。

發布數據幀后為什么會出現此錯誤

因為你沒有。 您所要做的就是在執行計划中添加一個名稱。 檢查點是最接近“釋放”的東西,但是您確實不希望在破壞性操作的中間松開執行器時陷入困境。

您可以寫入臨時目錄,刪除輸入並移動臨時文件,但實際上-只需使用適合該工作的工具即可。

以下是您可以嘗試的方法。

您可以使用saveAsTable API將其寫入另一個表中,而不必使用registertemptable api

dfFinal.write.mode("overwrite").saveAsTable("intermediate_result")

然后,將其寫入員工表

 val dy = sqlContext.table("intermediate_result")
  dy.write.mode("overwrite").insertInto("employees")

最后,刪除intermediate_result表。

我會這樣處理

>>> df = sqlContext.sql("select * from t")
>>> df.show()
+-------------+---------------+
|department_id|department_name|
+-------------+---------------+
|            2|        Fitness|
|            3|       Footwear|
|            4|        Apparel|
|            5|           Golf|
|            6|       Outdoors|
|            7|       Fan Shop|
+-------------+---------------+

為了模擬您的流程,我創建了2個數據幀,進行union並寫回到同一表 t (在此示例中,故意刪除department_id = 4

>>> df1 = sqlContext.sql("select * from t where department_id < 4")
>>> df2 = sqlContext.sql("select * from t where department_id > 4")
>>> df3 = df1.unionAll(df2)
>>> df3.registerTempTable("df3")
>>> sqlContext.sql("insert overwrite table t select * from df3")
DataFrame[]  
>>> sqlContext.sql("select * from t").show()
+-------------+---------------+
|department_id|department_name|
+-------------+---------------+
|            2|        Fitness|
|            3|       Footwear|
|            5|           Golf|
|            6|       Outdoors|
|            7|       Fan Shop|
+-------------+---------------+
  1. 從 DataFrame 中提取 RDD 和模式。

  2. 創建新的克隆 DataFame。

  3. 覆蓋表

private def overWrite(df: DataFrame): Unit = { val schema = df.schema val rdd = df.rdd val dfForSave = spark.createDataFrame(rdd, schema) dfForSave.write .mode(SaveMode.Overwrite) .insertInto(s"${tableSource.schema}.${tableSource.table}") }

可以說這是您正在讀取和覆蓋的配置單元表

請按如下所示將時間戳記添加到配置單元表位置

    create table table_name (
  id                int,
  dtDontQuery       string,
  name              string
)
 Location hdfs://user/table_name/timestamp

由於無法覆蓋,因此我們會將輸出文件寫入新位置。

使用數據框Api將數據寫入新位置

df.write.orc(hdfs://user/xx/tablename/newtimestamp/)

寫入數據后,將配置單元表位置更改為新位置

Alter table tablename set Location hdfs://user/xx/tablename/newtimestamp/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM