Scala 使用sparksql从配置单元表读取数据并写回
我正在使用Spark SQL读取配置单元表,并将其分配给scala valScala 使用sparksql从配置单元表读取数据并写回,scala,hadoop,apache-spark,apache-spark-sql,spark-dataframe,Scala,Hadoop,Apache Spark,Apache Spark Sql,Spark Dataframe,我正在使用Spark SQL读取配置单元表,并将其分配给scala val val x = sqlContext.sql("select * from some_table") 然后我对数据框x进行了一些处理,最后得到了一个数据框y,它具有与表some_table相同的模式 最后,我尝试将y数据帧插入到同一个配置单元表的某个\u表中 y.write.mode(SaveMode.Overwrite).saveAsTable().insertInto("some_table") 然后我得到了错误
val x = sqlContext.sql("select * from some_table")
然后我对数据框x进行了一些处理,最后得到了一个数据框y,它具有与表some_table相同的模式
最后,我尝试将y数据帧插入到同一个配置单元表的某个\u表中
y.write.mode(SaveMode.Overwrite).saveAsTable().insertInto("some_table")
然后我得到了错误
org.apache.spark.sql.AnalysisException:无法将覆盖插入也从中读取的表中
我尝试创建一个insert sql语句并使用sqlContext.sql()触发它,但它也给了我同样的错误
有没有办法绕过这个错误?我需要将记录插入到同一个表中
嗨,我试着按照建议去做,但仍然得到同样的错误
val x = sqlContext.sql("select * from incremental.test2")
val y = x.limit(5)
y.registerTempTable("temp_table")
val dy = sqlContext.table("temp_table")
dy.write.mode("overwrite").insertInto("incremental.test2")
scala> dy.write.mode("overwrite").insertInto("incremental.test2")
org.apache.spark.sql.AnalysisException: Cannot insert overwrite into table that is also being read from.;
您应该首先将数据帧
y
保存在临时表中
y.write.mode("overwrite").saveAsTable("temp_table")
然后可以覆盖目标表中的行
val dy = sqlContext.table("temp_table")
dy.write.mode("overwrite").insertInto("some_table")
实际上,您也可以使用检查点来实现这一点。由于Spark会中断数据沿袭,因此无法检测到您正在读取和覆盖同一个表:
sqlContext.sparkContext.setCheckpointDir(checkpointDir)
val ds = sqlContext.sql("select * from some_table").checkpoint()
ds.write.mode("overwrite").saveAsTable("some_table")
您应该首先将数据框y像拼花地板文件一样保存:
y.write.parquet("temp_table")
加载后,如下所示:
val parquetFile = sqlContext.read.parquet("temp_table")
完成后,在表中插入数据
parquetFile.write.insertInto("some_table")
在Spark 2.2的上下文中
Caused by: org.apache.spark.sql.AnalysisException: Cannot overwrite a path that is also being read from.;
at org.apache.spark.sql.execution.command.DDLUtils$.verifyNotReadPath(ddl.scala:906)
此错误发生在作业中,在该作业中,我们正在读取和写入同一路径。就像使用SCD逻辑的作业一样
解决方案-
从spark中的配置单元表读取数据:
val hconfig = new org.apache.hadoop.conf.Configuration()
org.apache.hive.hcatalog.mapreduce.HCatInputFormat.setInput(hconfig , "dbname", "tablename")
val inputFormat = (new HCatInputFormat).asInstanceOf[InputFormat[WritableComparable[_],HCatRecord]].getClass
val data = sc.newAPIHadoopRDD(hconfig,inputFormat,classOf[WritableComparable[_]],classOf[HCatRecord])
在执行以下操作的情况下,还会出现错误:“无法覆盖正在读取的路径”:
这就像切割您所在的分支:-(在执行以下操作之前,您需要记住的是,您要覆盖的配置单元表应该是由配置单元DDL创建的,而不是由
spark(df.write.saveAsTable("<table_name>"))
spark(df.write.saveAsTable(“”)
如果上述情况不正确,这将不起作用。
我在spark 2.3.0中对此进行了测试
val tableReadDf=spark.sql("select * from <dbName>.<tableName>")
val updatedDf=tableReadDf.<transformation> //any update/delete/addition
updatedDf.createOrReplaceTempView("myUpdatedTable")
spark.sql("""with tempView as(select * from myUpdatedTable) insert overwrite table
<dbName>.<tableName> <partition><partition_columns> select * from tempView""")
val tableReadDf=spark.sql(“选择*from.”)
val updatedf=tableReadDf//任何更新/删除/添加
updatedDf.createOrReplaceTempView(“myUpdatedTable”)
spark.sql(“”),tempView为(从MyUpdateTable中选择*插入覆盖表
。从临时视图“”中选择*)
再次出现相同的错误。使用代码段编辑了我的问题抱歉,我已编辑了我的答案。RegisterAstetrable将创建内存中的表,从而产生相同的错误。使用saveAsTable时,它应该可以工作(但随后会将其写入磁盘,之后必须删除该表)。抱歉,我没有看到其他备选方案。答,我用同样的逻辑处理了这种情况,但我觉得这不划算。你突出强调的一点,即写入磁盘,是我想跳过的部分。无论如何,感谢你的帮助@cheseaux。如果你在这方面找到好的东西,请告诉我。干杯!!这完全安全吗?如果pp在写入目标表时失败?结果不是空的吗?(因此,当Thread自动重试你的应用程序时,你可能会提供错误的结果)我知道这很笨拙,但你不能截断原始表,然后将所有内容写回它吗?