踩坑Hive的动态写入

在Spark on hive中,创建表有三种方式

  • CREATE TABLE USING DATA_SOURCE
  • CREATE TABLE USING HIVE FORMAT
  • CREATE TABLE LIKE

方式1创建的是 data source 表,方式2 创建的是hive serde 表,方式3创建的表和like的表保持一致。

那么data source 表和 hive serde 表在使用上有什么区别呢?

hive serde 表

hive serde表,开启动态分区,使用动态写入时候,必须要开启下面的参数:

1
set hive.exec.dynamic.partition=true;

严格模式要求至少有一个静态分区,如果我们写入的表只有一个分区字段,是需要开启非严格模式的:

1
set hive.exec.dynamic.partition.mode=nonstrict;

如果不开启动态分区,直接动态写入是会报错的。

data source 表

data source 表和 hive serve,开启动态分区的参数有一些区别:

默认情况下是static模式,使用如下参数开启动态分区:

1
set spark.sql.sources.partitionOverwriteMode=DYNAMIC;

如果不开启动态分区,使用动态写入不会报错,而且被写入的表,所有分区都会先被全部删除!然后动态写入查询的内容。

1
2
3
4
set spark.sql.sources.partitionOverwriteMode=static;
insert overwrite table pama.text_002 partition(dt)
select * from pama.text_001
;

举个例子,上面语句执行完毕后,pama.text_002表中所有的分区会被删除,然后把pama.text_001的内容写入pama.text_002。然而这是一个深坑。

所谓动态分区,即不指定分区的详细信息,分区信息由查询内容决定。

如果我开启了静态分区模式,在使用动态语句插入时候,为什么还会被动态执行且不报异常?

这是一个bug还是一个feature?

spark.sql.sources.partitionOverwriteMode STATIC When INSERT OVERWRITE a partitioned data source table, we currently support 2 modes: static and dynamic. In static mode, Spark deletes all the partitions that match the partition specification(e.g. PARTITION(a=1,b)) in the INSERT statement, before overwriting. In dynamic mode, Spark doesn’t delete partitions ahead, and only overwrite those partitions that have data written into it at runtime. By default we use static mode to keep the same behavior of Spark prior to 2.3. Note that this config doesn’t affect Hive serde tables, as they are always overwritten with dynamic mode. This can also be set as an output option for a data source using key partitionOverwriteMode (which takes precedence over this setting), e.g. dataframe.write.option(“partitionOverwriteMode”, “dynamic”).save(path).

参考:https://spark.apache.org/docs/3.2.0/configuration.html#dynamic-allocation