Spark如何正确的写hive分区表

Spark——Spark覆盖分区表中指定的分区 文章目录项目场景问题描述解决方案参考 项目场景 我们现在有这样一个表,需要按月来记录用户的状态,当前月的状态数据是每天都要更新的,历史月的状态数据导入到表之后就不再更新了。 那么这个业务场景就转换成了“如何向一个已存在的分区表写入并覆盖当前月份的状态数据,而又保留历史月份数据”的问题。 问题描述 Spark中向分区表写数据的时候,如果写入模式为“overwrite”,那会将整个表覆盖掉;如果写入模式为“append”,那么我们当前一个月的数据每天都会追加到当前月的分区内,那就会造成数据重复。所以不能直接使用 阅读详情
AI摘要

本文详细介绍了在Spark中使用Hive分区表时,如何正确设置`spark.sql.sources.partitionOverwriteMode`和`hive.exec.dynamic.partition.mode`参数,以避免因误操作导致的全表覆盖。通过实例演示了不同写入方法对动态分区的影响,以及如何指定动态分区和静态分区的使用规则。

经常听到有人讲:spark写hive 分区表时,原本想覆盖一个分区的数据,但因为错误的编码导致整个表的分区被覆盖。本文针对此问题进行测试。

1. 测试结论

蓝色字体表示推荐方式

  1. 需要指定如下参数:"spark.sql.sources.partitionOverwriteMode", "dynamic"  "hive.exec.dynamic.partition.mode", "nonstrict"

  2. saveAsTable方法会导致全表覆盖写,需要用insert into,详情下面的源代码

  3. insert into需要主要DataFrame列的顺序要和hive表里的顺序一致

操作方式效果
df1.write.mode("overwrite").partitionBy("year").saveAsTable(tableName)所有分区被覆盖
df1.write.mode("overwrite").format("Hive").partitionBy("year").saveAsTable(tableName)所有分区被覆盖
df1.write.option("partitionOverwriteMode", "dynamic").mode("append").insertInto(tableName)动态分区,如果分区存在则追加
df1.write.option("partitionOverwriteMode", "dynamic").mode("overwrite").insertInto(tableName)动态分区,如果分区存在则覆盖
INSERT OVERWRITE TABLE $tableName partition (year) SELECT * FROM tmp动态分区,如果分区存在则覆盖
INSERT INTO TABLE $tableName partition (year) SELECT * FROM tmp动态分区,如果分区存在则追加
df1.write.mode("overwrite").insertInto(tableName)动态分区,如果分区存在则覆盖
df1.write.mode("append").insertInto(tableName)动态分区,如果分区存在则追加
INSERT OVERWRITE TABLE $tableName partition (year=2024) SELECT * FROM tmp针对指定分区覆盖写入
INSERT INTO TABLE $tableName partition (year=2024) SELECT * FROM tmp针对指定分区追加数据

1.1. 参数说明

1.1.1. hive.exec.dynamic.partition.mode

hive.exec.dynamic.partition.mode: 默认值是strict,即不允许分区列全部是动态的,目的是为了防止用户有可能原意是只在子分区内进行动态建分区,但是由于疏忽忘记为主分区列指定值了,这将导致一个dml语句在短时间内创建大量的新的分区(对应大量新的文件夹),对系统性能带来影响。 如果指定为nonstrict,则允许所有的分区列都是动态分区列

insert overwrite table partition_test partition(stat_date='20110728',province) select member_id,name,province from partition_test_input where stat_date='20110728';

stat_date叫做静态分区列,province叫做动态分区列。select子句中需要把动态分区列按照分区的顺序写出来,静态分区列不用写出来。

这样stat_date='20110728'的所有数据,会根据province的不同分别插入到/user/hive/warehouse/partition_test/stat_date=20110728/下面的不同的子文件夹下,如果源数据对应的province子分区不存在,则会自动创建,非常方便,而且避免了人工控制插入数据与分区的映射关系存在的潜在风险。

注意,动态分区不允许主分区采用动态列而副分区采用静态列,这样将导致所有的主分区都要创建副分区静态列所定义的分区:

hive> insert overwrite table partition_test partition(stat_date,province='gd')  select member_id,name,province from partition_test_input where province='gd';
       FAILED: Error in semantic analysis: Line 1:48 Dynamic partition cannot be the parent of a static partition 'gd'

相关的参数如下:

  • hive.exec.dynamic.partition=true : 开启动态分区 
  • hive.exec.max.dynamic.partitions.pernode (缺省值100):每一个mapreduce job允许创建的分区的最大数量,如果超过了这个数量就会报错
  • hive.exec.max.dynamic.partitions (缺省值1000):一个dml语句允许创建的所有分区的最大数量
  • hive.exec.max.created.files (缺省值100000):所有的mapreduce job允许创建的文件的最大数量

1.1.2. spark.sql.sources.partitionOverwriteMode

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).

当INSERT OVERWRITE 一个已分区的数据源表时,我们目前支持两种模式:静态和动态。在静态模式下,Spark会删除所有符合分区规格的分区。PARTITION(a=1,b))在INSERT语句中,然后overwriting。在动态模式下,Spark不会提前删除分区,只会在运行时覆盖那些已经写入数据的分区。默认情况下,我们使用静态模式来保持Spark 2.3之前的相同行为。注意,这个配置不会影响Hive serde表,因为它们总是被动态模式覆盖。也可以使用partitionOverwriteMode将其设置为数据源的输出选项(优先于此设置),例如dataframe.write.option("partitionOverwriteMode", "dynamic").save(path)

相关参数如下:

spark.sql.sources.partitionColumnTypeInference.enabled:如果为true,则自动推断已分区列的数据类型。

spark.sql.statistics.fallBackToHdfs:当为true时,如果表元数据中没有表的统计信息,它将返回到HDFS。这在确定一个表是否足够小到可以使用广播连接时非常有用。这个标志只对非分区的Hive表有效。对于非分区的数据源表,如果表统计信息不可用,将自动重新计算它。对于分区数据源和分区Hive表,如果表统计信息不可用,则为'spark.sql.defaultSizeInBytes'。

1.2. 查看hive分区命令

  1.  show partitions test_partition;
  2.  desc test_partition partition (year=2018)
  3. desc extended test_partition partition (year=2018)

2. 测试源代码 

object SparkHiveTest {

  def main(args: Array[String]): Unit = {
    testHivePartitionOverwrite();
  }

  def testHivePartitionOverwrite(): Unit = {
    val spark = SparkSession
      .builder()
      .appName("testHivePartitionOverwrite")
      .master("local[2]")
      // 必须替换为自己的hivemetastore service's thrift url
      .config("hive.metastore.uris", "thrift://172.25.20.170:9083")
      .config("spark.sql.parquet.writeLegacyFormat", true)
      .config("spark.sql.sources.partitionOverwriteMode", "dynamic")
      .config("hive.exec.dynamic.partition.mode", "nonstrict")
      .enableHiveSupport()
      .getOrCreate()

    import spark.sql

    val data = Array(
      ("001", "张三", 21, "2017"), ("002", "李四", 18, "2018"),
      ("001", "王五", 21, "2019"), ("002", "赵六", 18, "2020"),
      ("001", "王二麻子", 21, "2021"), ("002", "马顺子", 18, "2022")
    )

    val df = spark.createDataFrame(data).toDF("id", "name", "age", "year")
    //创建临时表
    df.createOrReplaceTempView("temp_table")

    val tableName = "test_partition"
    //切换hive的数据库
    sql("use default")
    // 1、创建分区表,并写入数据
    df.write.mode("overwrite").partitionBy("year").saveAsTable(tableName)
    spark.table(tableName).show()

    val data1 = Array(("011", "李太白", 21, "2018"), ("011", "李商隐", 21, "2018"), ("011", "李清照", 21, "2023"))
    val df1 = spark.createDataFrame(data1).toDF("id", "name", "age", "year")
    //以下两种写法都会对全表覆盖
    //df1.write.mode("overwrite").partitionBy("year").saveAsTable(tableName)
    //df1.write.mode("overwrite").format("Hive").partitionBy("year").saveAsTable(tableName) //不成功,全表覆盖
//    df1.write.option("partitionOverwriteMode", "static").mode("overwrite").insertInto(tableName)
//    df1.write.option("partitionOverwriteMode", "dynamic").mode("append").insertInto(tableName)

    //以下两种写法都是动态分区,如果分区已经存在,则覆盖写入, 如果替换为append,则是追加写入
    //        df1.write.mode("overwrite").insertInto(tableName)
    //采用SQL方式,如果分区已经存在,则覆盖写入, 如果替换为INTO,则是追加写入
    df1.createOrReplaceTempView("tmp")
    val sqlStr =
      s"""
         |INSERT OVERWRITE TABLE $tableName partition (year)
         |SELECT * FROM tmp
      """.stripMargin
    sql(sqlStr);

    //指定分区写入
    //    val data2:Array[(String,String,Int)] = Array()
    //    val df2 = spark.createDataFrame(data2).toDF("id", "name", "age")
    //    df2.createOrReplaceTempView("tmp")
    //    val sqlStr =
    //      s"""
    //         |INSERT INTO TABLE $tableName partition (year=2026)
    //         |SELECT * FROM tmp
    //          """.stripMargin
    //    spark.sql(sqlStr);

    //打印表中的数据
    //    spark.table(tableName).show()
    sql("select * from test_partition").foreach(println(_))

    spark.stop
  }
}

参考

https://www.cnblogs.com/tree1123/p/13440952.html

https://www.cnblogs.com/liqiu/p/4095654.html

http://spark.apache.org/docs/2.4.7/configuration.html#spark-sql

https://spark.apache.org/docs/latest/configuration.html

 

 

pyspark--写hive分区表覆盖指定分区数据 初次写入分区数据 spark写入hive分区表时,如果数据表事先不存在,可以选择手动建表,可以使用以下代码写入数据,会自动创建数据表: df = spark.createDataFrame([(1, "alice", "20220412"), (2, "bob", "20220412")], ["id", "name", "date"]) df.show() df.write.format("orc").mode("overwrite").partitionBy("date").saveAsTable("t 阅读详情

相关推荐

spark把kafka数据写到hive

写入分区表: 准备工作:先建好分区表 方法一:(使用dataframe) 写数据到数据所在的位置,因为hive分区的本质就是分文件夹,先用spark把数据写到文件夹位置,然后执行sql添加分区 1.写数据到文件夹 //df为DataFrame df.write.mode(SaveMode.Overwrite).format("parquet") .partitionBy("day" , "dev_platform" ).save(outputPath) 2.寻找刚刚数据新建的.

Sivan 4211

Spark操作Hive分区表

原作者写的比较清楚了,特别是DDL建了表后,又用Spark向表里写数据常常写不进去,会报异常。 原文地址:https://dongkelun.com/2018/12/04/sparkHivePatition/ 前言 前面学习总结了Hive分区表,现在学习总结一下Spark如何操作Hive分区表,包括利用Spark DataFrame创建Hive的分区表和Spark向已经存在Hive分区表里插...

xiaoxiaohacker的专栏 2842

Spark写入Hive分区表的完整指南

在Spark中,将数据写入Hive分区表是一个常见的任务。本文将为您提供关于如何使用Spark将数据保存为Hive表并插入到分区的详细指南。通过以上步骤,您可以使用Spark将数据保存或插入到Hive分区表中。上述代码创建了一个SparkSession实例,配置了Hive的仓库目录,并启用了Hive支持。在上述示例中,我们首先创建了一个包含要保存的数据的DataFrame。在上述示例中,我们创建了一个包含要插入的数据的DataFrame,并使用。插入操作会根据数据的分区列将数据放入正确的分区。

HackWhisper的博客 1169

spark读取数据写入hive数据表

pyspark 从已有数据表读取数据写入目标hive表的代码模板

wangwangstone的博客 6566

Spark 覆盖写Hive分区表,只覆盖部分对应分区

我的原创地址:https://dongkelun.com/2020/01/16/sparkHivePartitionOverwrite/ 前言 总结Spark覆盖写Hive分区表,如何只覆盖部分对应分区 版本 要求Spark版本2.3以上,亲测2.2无效 配置 config("spark.sql.sources.partitionOverwriteMode","dynamic") 注意 1、saveAsTable方法无效,会全表覆盖写,需要用insertInto,详情见代码 2、insertInto需要主

主要分享大数据相关的知识,如Spark、Hudi 3212

Ubuntu视频播放器怎么选?VLC、mpv、SMPlayer硬解与字幕配置指南

在Linux系统中,视频播放体验取决于播放器、解码器与显卡驱动的协同。硬件解码通过VA-API或VDPAU将解码任务交给GPU,能显著降低CPU占用,解决4K高码率视频卡顿问题。对于Ubuntu用户,合理配置解码环境与播放器,可流畅播放HEVC、多音轨及ASS特效字幕视频。无论是日常观影、番剧追更还是家庭影院场景,选择合适的播放器并正确启用硬解,都是提升体验的关键。本文围绕Ubuntu平台,详解VLC、mpv、SMPlayer等播放器的安装、硬解配置与常见问题排查,帮助你在Linux上获得流畅的本地视频播放

weixin_33801856的博客 508

Spark将Dataframe数据写入Hive分区表的方案

DataFrame 将数据写入hive中时,默认的是hive默认数据库,insert into没有指定数据库的参数,数据写入hive表或者hive表分区中:1、将Data...

微信搜:import_bigdata,大数据领域硬核原创作者 9408

CoppeliaSim+matlab+simulink七轴机械臂仿真

七轴机械臂vrep+matlab+simulink 仿真

a1233219的博客 3553

spark 将dataframe数据写入Hive分区表

1、将DataFrame数据写入到Hive表中 从DataFrame类中可以看到与hive表有关的写入Api有以下几个: registerTempTable(tableName: String): Unit, insertInto(tableName: String): Unit insertInto(tableName: String, overwrite: Boolean): Unit sav...

ChengYanan的博客 2470

学习海康VisionMaster之表面缺陷滤波

本文介绍了VisionMaster中表面缺陷滤波技术的应用。该技术通过数学变换抑制背景干扰、增强缺陷特征,适用于电池铝壳、垫圈/螺丝等无纹理背景的表面缺陷检测(划痕、凹坑、异物等)。操作流程包括:图像导入、轮廓定位、位置修正、参数设置(重点讲解滤波核尺寸/数量/标准差等关键参数的调整策略)。文章通过案例演示了如何通过多方向滤波响应识别表面划伤,并指出需结合blob分析进一步优化检测结果。该技术对工业质检具有实用价值,参数设置需结合缺陷特征与背景特性灵活调整。

yuhouxiyang的专栏 2829

使用RepeatModeler和RepeatMasker注释基因组重复序列

重复序列注释有两种常用策略,基于同源序列相似性和基于重复序列结构特征。RepeatMasker是基于同源序列相似性注释序列的常用工具, RepeatModeler可用来从头对基因组的重复序列家族进行建模注释,它的核心组件是RECON和RepatScout。 这篇教程介绍如何使用RepeatModeler从头鉴定基因组的重复序列,之后用RepeatMasker根据自...

xuzhougeng blog 8854

spark使用insertInto存入hive分区表中

把spark的处理结果存入hive分区表中,可以直接在sql中设定分区即可,可以使用withColumn算子执行 ss.sql("SELECT merchant_id,platform," + "case when trim(first_channel_id) = '' or first_channel_id is null then '-1' else first_cha...

ZH519080的博客 6201

项目回顾一:《高速多端口共享缓存模块》

本帖子仅为了回顾一下一年前自己动手完成的第一个数字ic设计项目的历程,为复试做一下准备,完成的这个sramc模块花了整整四个月的时间,从0到12个模块的代码产出以及模块的验证,虽然没有拿奖,也没有进入复赛,设计过程中使用的技术手段和算法也不太成熟,但这这是一个值得记录的过程!

weixin_60261760的博客 1255

spark写表指定外部表_spark 将dataframe数据写入Hive分区表

从spark1.2 到spark1.3,spark SQL中的SchemaRDD变为了DataFrame,DataFrame相对于SchemaRDD有了较大改变,同时提供了更多好用且方便的API。DataFrame将数据写入hive中时,默认的是hive默认数据库,insertInto没有指定数据库的参数,本文使用了下面方式将数据写入hive表或者hive表的分区中,仅供参考。1、将DataFra...

weixin_29147347的博客 1776

13、网络通信中的字节序与内存测试

本文主要探讨了网络通信中的字节序问题以及嵌入式系统中内存测试的相关内容。在网络通信部分,重点分析了大端序和小端序的差异,以及TCP/IP协议中字节序的转换机制,并介绍了相关的宏定义和实现方法。在内存测试部分,详细阐述了内存测试的目的、常见问题以及具体的测试策略,包括数据总线测试、地址总线测试和设备测试。通过这些内容,嵌入式程序员可以更好地理解并解决实际开发中可能遇到的字节序和内存问题,从而提高系统的稳定性和可靠性。

mmm90的博客 111

【Unity的HDRP渲染管线下用Steam VR串流结合使用遇到的各种问题_SteamVR 插件和Pico串流助手】

当你启用"Mock Runtime"选项后,Unity将模拟一个虚拟的OpenXR运行时环境,并提供一些虚拟的设备和功能,让你能够进行开发和调试。在Unity中,SteamVR插件是一个由Valve提供的Unity插件,它允许开发者在Unity项目中集成SteamVR功能,以便支持SteamVR设备。OpenXR是一个跨平台的虚拟和增强现实(VR/AR)开发接口,它为开发者提供了一个统一的接口,用于访问不同VR/AR硬件设备和平台的功能。这个选项是用于模拟OpenXR运行时环境的功能。

暴走约伯的博客 2800

Spark添加数据至Hive分区表

准备工作: 创建hive分区表 create table login_origin( created_date string, event_id string, dev_mac string, domain string, session_id string, dev_na...

chilai4545的博客 1545

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Spark写入hive表时saveAsTable和insertInto的区别/Spark插入hive分区表的一些坑(原创)

Spark写入hive表时saveAsTable和insertInto的区别/Spark插入hive分区表的一些坑(原创) # 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。 新的改变 我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客: 全新的界面设计 ,将会

huihuixia123的博客 8835

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

spark 将dataframe数据写入Hive分区表

从spark1.2 到spark1.3,spark SQL中的SchemaRDD变为了DataFrame,DataFrame相对于SchemaRDD有了较大改变,同时提供了更多好用且方便的API。DataFrame将数据写入hive中时,默认的是hive默认数据库,insertInto没有指定数据库的参数,本文使用了下面方式将数据写入hive表或者hive表的分区中,仅供参考。1、将DataFra...

weixin_33939843的博客 2304

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Spark写入非分区表Hive无法读取的问题

问题描述: Spark2.4写入的非分区表无法使用Hive2.1.1版本的引擎去读取,报错:`Failed with exception java.io.IOException:java.lang.ArrayIndexOutOfBoundsException: 6` 原因分析: 一、非分区表测试 --1. 新建测试表 create table tmp.orc(id int, name string) stored as orc; --2.sparksql写入 insert into table t

欲望以提升热忱 毅力以磨平高山 1029

hive 分区表_Spark将Dataframe数据写入Hive分区表的方案

DataFrame 将数据写入hive中时,默认的是hive默认数据库,insert into没有指定数据库的参数,数据写入hive表或者hive表分区中:1、将DataFrame数据写入到hive表中从DataFrame类中可以看到与hive表有关的写入API有一下几个:registerTempTable(tableName:String):Unit,inserInto(tableNa...

weixin_39734987的博客 1313

spark-使用DataFrameWriter或者spark-sql向hive分区表中插入数据

saveAsTable 在此方法中,如果数据源表存在于Spark-catalog中,则使用save方法参数中的模式来确定如何插入。如果表不在Spark-catalog中,我们总是会覆盖它(比如JDBC数据源中的一个表),因为spark可以整合hive,所以hive中的表在Spark-catalog中,但比如spark创建的临时表,就不在Spark-catalog中。如果表在Spark-catalog中,则追加。 如果df根据一个没分区的 hive表创建,并且可以转换为hive内置的序列化器(比如ORC和P

DCHAO的博客 5326
上一篇: spark执行优化--禁止将依赖的Jar包传到HDFS(spark.yarn.jar和spark.yarn.archive的使用)
下一篇: spark如何正确的删除hive外部表【删除表时同时删除hdfs上的数据】?
enjoy编程
enjoy编程 领域专家: 大数据技术领域 领域专家: 大数据技术领域
博客等级 码龄20年 4万+粉丝 578原创
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

enjoy编程

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

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

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

打赏作者

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

抵扣说明:

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

余额充值