[英]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.