spark-hive-向动态分区配置单元表中更新会引发错误-分区规范包含非分区列

时间:2018-08-06 18:46:42

标签: apache-spark hive parquet

我正在使用spark 2.2.1和hive2.1。我试图将覆盖多个分区插入现有分区的蜂巢/镶木表中。

表是使用sparkSession创建的。

我有一个带有分区P1和P2的表“ mytable”。

我在sparkSession对象上设置了以下内容:

"hive.exec.dynamic.partition"=true
"hive.exec.dynamic.partition.mode"="nonstrict"

代码:

val df = spark.read.csv(pathToNewData) df.createOrReplaceTempView("updateTable") //here 'df' may contains data from multiple partitions. i.e. multiple values for P1 and P2 in data.

spark.sql("insert overwrite table mytable PARTITION(P1, P2) select c1, c2,..cn, P1, P2 from updateTable") // I made sure that partition columns P1 and P2 are at the end of projection list.

我遇到以下错误:

org.apache.spark.sql.AnalysisException: org.apache.hadoop.hive.ql.metadata.Table.ValidationFailureSemanticException: Partition spec {p1=, p2=, P1=1085, P2=164590861} contains non-partition columns;

数据帧'df'具有记录P1 = 1085,P2 = 164590861。看起来像是套管问题(下部与上部)。我在查询中尝试了两种情况,但仍然无法正常工作。

编辑:

Insert语句可用于静态分区,但这不是我想要的: 例如以下作品

spark.sql("insert overwrite table mytable PARTITION(P1=1085, P2=164590861) select c1, c2,..cn, P1, P2 from updateTable where P1=1085 and P2=164590861")

创建表stmt:

CREATE TABLE my_table ( c1 int, c2 int, c3 string, p1 int, p2 int) PARTITIONED BY ( p1 int, p2 int) ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' STORED AS INPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat' LOCATION 'maprfs:/mds/hive/warehouse/my.db/xc_bonus' TBLPROPERTIES ( 'spark.sql.partitionProvider'='catalog', 'spark.sql.sources.schema.numPartCols'='2', 'spark.sql.sources.schema.numParts'='1', 'spark.sql.sources.schema.part.0'='{.spark struct metadata here.......}'; 'spark.sql.sources.schema.partCol.0'='P1', //Spark is using Capital Names for Partitions; while hive is using lowercase 'spark.sql.sources.schema.partCol.1'='P2', 'transient_lastDdlTime'='1533665272')

在上面,spark.sql.sources.schema.partCol.0使用所有大写字母,而PARTITIONED BY语句将所有小写字母用于分区列

2 个答案:

答案 0 :(得分:0)

基于异常,还假定表“ mytable”已创建为一个分区表,其中P1和P2为分区。克服此异常的一种方法是在执行命令之前手动强制使用虚拟分区。尝试做

spark.sql(“更改表mytable添加分区(p1 =默认,p2 =默认)”)。

成功后,执行插入覆盖语句。希望这会有所帮助吗?

答案 1 :(得分:0)

正如我在EDIT一节中提到的,问题实际上是蜂巢和spark之间的分隔栏大小写不同(下部与上部)!我用所有大写字母创建了蜂巢表,但蜂巢仍在内部将其存储为小写字母,但火花元数据按照我的意图保留为大写。使用所有小写的分区列修复create语句,可以解决后续更新的问题! 如果您使用的是hive 2.1和spark 2.2,请确保create语句中的以下属性具有相同的大小写。

PARTITIONED BY ( 
p1int, 
p2int)
'spark.sql.sources.schema.partCol.0'='p1', 
  'spark.sql.sources.schema.partCol.1'='p2',