Spark DataFrame中insertInto()与saveAsTable()区别及动态分区插入hive表使用设置

本文详细介绍了Spark中将DataFrame数据插入Hive表的两种方法:insertInto和saveAsTable,以及它们的区别。insertInto要求DataFrame的schema与Hive表匹配,而saveAsTable可以自动调整列顺序。此外,还讨论了通过SparkSQL进行插入操作,并提到了动态分区的配置和实现,强调了动态分区在Hive和Spark中的设置及其在数据插入中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

@Author  : Spinach | GHB
@Link    : http://blog.youkuaiyun.com/bocai8058


前言

在spark应用开发中,会经常需要将数据清洗后的结果,插入HIVE表中。而针对数据落表,官方提供了几种插入方式,具体有insertIntosaveAsTable调用spark sql。下面我们一一讲解他们的区别。

在这里插入图片描述
在这里插入图片描述

insertInto()

保存DataFrame数据到指定hive表中,但要求满足以下两点:

  1. 指定的hive表是存在的;
  2. DataFrame的schema结构顺序与指定Hive表的schema结构顺序是一致的。
  • insertInto(tableName: String) 将数据插入到指定的tableName中
scala> Seq((1, 2)).toDF("i", "j").write.mode("overwrite").saveAsTable("t1")
scala> Seq((3, 4)).toDF("j", "i").write.insertInto("t1")
scala> Seq((5, 6)).toDF("a", "b").write.insertInto("t1")
scala> sql("select * from t1").show
+---+---+
|  i|  j|
+---+---+
|  5|  6|
|  3|  4|
|  1|  2|
+---+---+

saveAsTable()

保存DataFrame数据到指定hive表中。分两种情况:表已经存在表不存在

  1. 如果表不存在,则会自动创建表结构。

  2. 如果表已经存在,则此函数的行为取决于由mode函数指定的保存模式(默认情况下抛出异常)。
    a.mode=Overwrite时

    1. 当dataframe的schema与已存在的schema个数相同:DataFrame中的列顺序不需要与现有表的列顺序相同,与insertInto不同,saveAsTable将使用列名称查找正确的列位置。(与insertInto区别点)
    2. 当dataframe的schema与已存在的schema个数不同:会撇弃原有的schema,按照dataframe的schema重新创建并插入。

    b.mode=Append时

    1. 当dataframe的schema与已存在的schema个数相同:DataFrame中的列顺序不需要与现有表的列顺序相同。
    2. 当dataframe的schema与已存在的schema个数不同:会报错。
  • saveAsTable(tableName: String) 将数据插入到指定的tableName中
scala> Seq((1, 2)).toDF("i", "j").write.mode("overwrite").saveAsTable("t1")
scala> Seq((3, 4)).toDF("j", "i").write.mode("append").saveAsTable("t1")
scala> sql("select * from t1").show
+---+---+
|  i|  j|
+---+---+
|  1|  2|
|  4|  3|
+---+---+

调用spark sql

创建createOrReplaceTempView或createOrReplaceGlobalTempView,然后使用spark sql插入到指定hive表中,但要求满足以下两点:

  1. 指定的hive表是存在的;
  2. createOrReplaceTempView的schema结构顺序与指定Hive表的schema结构顺序是一致的。
val viewTmp = "tmpView1" + date
tmpModelDS.createOrReplaceTempView(viewTmp)
spark.sql(s"""
               |insert overwrite table $tableName
               |partition(date='$date')
               |select * from $viewTmp
      	   """.stripMargin.trim)

注意:createOrReplaceTempView是只注册可以通过Hive查询访问的数据帧,它只是用于df的DAG的标识符。

动态分区参数设置及代码实现

如果支持动态分区,需要对Hive或spark设置如下参数:

  • 针对Hive任务
# hive动态参数设置
set hive.exec.dynamici.partition=true; #开启动态分区,默认是false
set hive.exec.dynamic.partition.mode=nonstrict; #开启允许所有分区都是动态的,否则必须要有静态分区才能使用

# hive实现
insert overwrite table tmpTable partition(date)
select * from viewTmp; 
  • 针对Spark任务
//spark动态参数设置
SparkSession.builder()
.config("hive.exec.dynamic.partition", "true") //开启动态分区,默认是false
.config("hive.exec.dynamic.partition.mode", "nonstrict") //开启允许所有分区都是动态的,否则必须要有静态分区才能使用

//sparksql实现
tmpModelDS.write.mode(SaveMode.Overwrite).insertInto(tableName)

引用:http://spark.apache.org/docs/2.3.3/api/scala/index.html#org.apache.spark.sql.DataFrameWriter
http://spark.apache.org/docs/2.3.3/api/scala/index.html#org.apache.spark.sql.Dataset

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小学僧来啦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值