我定期运行的进程将数据写入配置为"spark.sql.sources.partitionOverwriteMode" = "dynamic"
的parquet文件上的表使用以下代码:
if (!tableExists) {
df.write
.mode("overwrite")
.partitionBy("partitionCol")
.format("parquet")
.saveAsTable("tablename")
}
else {
df.write
.format("parquet")
.mode("overwrite")
.insertInto("table")
}
如果表不存在并且在第一个子句中创建,它会正常工作,并且在下一次运行时,当表存在并且运行else子句时,它会正常工作。
然而,当我通过hive会话或使用spark.sql("CREATE TABLE...")
在现有的parquet文件上创建表时,然后运行该进程,它无法写入错误:
org.apache.spark.SparkException: Dynamic partition strict mode requires at least one static partition column. To turn this off set hive.exec.dynamic.partition.mode=nonstrict
将此配置添加到spark conf中解决了问题,但我不明白为什么通过命令创建表时需要它,而在使用saveAsTable
创建表时不需要它。
另外,我不明白这个配置是如何与spark相关的。据我所知,这里的静态分区意味着我们直接指定要写入的分区,而不是指定要按哪个列进行分区。是否有可能在spark中做这样的插入(与HiveQL相反)?
Spark 2.4, Hadoop 3.1
以下2个设置不完全相同。
hive.exec.dynamic.partition.mode
https://cwiki.apache.org/confluence/display/Hive/Configuration +属性spark.sql.sources.partitionOverwriteMode
https://spark.apache.org/docs/latest/configuration.html
对于spark,它控制是否在插入之前删除分区。
对于hive设置,它用于控制insert中的语法。在严格模式下,它至少需要一个静态分区,而在非严格模式下,所有分区都可以是动态的。