[英]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)
我的問題是:
我的方法是否正確,以更改兩名員工的部門
它不是。 只是為了重復在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|
+-------------+---------------+
從 DataFrame 中提取 RDD 和模式。
創建新的克隆 DataFame。
覆蓋表
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.