ALTER TABLE 分区操作-动态增加一级,多级分区,动态删除分区

本文介绍了如何在 Spark 3.x 中使用 Iceberg 进行分区操作,包括添加和删除分区。示例展示了创建表、插入数据、添加分区字段(如 loc 和 years(ts))、删除分区字段(loc 和 years(ts))的过程,以及在 Hive Catalog 中的操作。测试代码详细展示了这些操作的实现。

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

1.8.5.6 ALTER TABLE 分区操作

alter 分区操作包括增加分区和删除分区操作,这种分区操作在Spark3.x之后被支持,spark2.4版本不支持,并且使用时,必须在spark配置中加入spark.sql.extensions属性,其值为:org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions,在添加分区时还支持分区转换,语法如下:

  • 添加分区语法:ALTER TABLE ... ADD PARTITION FIELD
  • 删除分区语法:ALTER TABLE ... DROP PARTITION FIELD

具体操作如下:

  1. 创建表mytbl,并插入数据
val spark: SparkSession = SparkSession.builder().master("local").appName("SparkOperateIceberg")
  //指定hadoop catalog,catalog名称为hadoop_prod
  .config("spark.sql.catalog.hadoop_prod", "org.apache.iceberg.spark.SparkCatalog")
  .config("spark.sql.catalog.hadoop_prod.type", "hadoop")
  .config("spark.sql.catalog.hadoop_prod.warehouse", "hdfs://mycluster/sparkoperateiceberg")
  .config("spark.sql.extensions","org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions")
  .getOrCreate()

//1.创建普通表
spark.sql(
  """
    | create table hadoop_prod.default.mytbl(id int,name string,loc string,ts timestamp) using iceberg
  """.stripMargin)
//2.向表中插入数据,并查询
spark.sql(
  """
    |insert into hadoop_prod.default.mytbl values
    |(1,'zs',"beijing",cast(1608469830 as timestamp)),
    |(3,'ww',"shanghai",cast(1603096230 as timestamp))
  """.stripMargin)
spark.sql("select * from hadoop_prod.default.mytbl").show()

在HDFS中数据存储和结果如下:

  1. 将表loc列添加为分区列,并插入数据,查询
//3.将 loc 列添加成分区,必须添加 config("spark.sql.extensions", "org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions") 配置
spark.sql(
  """
    |alter table hadoop_prod.default.mytbl add partition field loc
  """.stripMargin)

//4.向表 mytbl中继续插入数据,之前数据没有分区,之后数据有分区
spark.sql(
  """
    |insert into hadoop_prod.default.mytbl values
    |(5,'tq',"hangzhou",cast(1608279630 as timestamp)),
    |(2,'ls',"shandong",cast(1634559630 as timestamp))
  """.stripMargin )
spark.sql("select * from hadoop_prod.default.mytbl").show()

在HDFS中数据存储和结果如下:

注意:添加分区字段是元数据操作,不会改变现有的表数据,新数据将使用新分区写入数据,现有数据将继续保留在原有的布局中

我的测试:

测试代码:

package com.shujia.spark.iceberg

import org.apache.spark.sql.SparkSession

object AlterTablePartition {
  def main(args: Array[String]): Unit = {

    /**
     * alter 分区操作包括增加分区和删除分区操作,这种分区操作在Spark3.x之后被支持,spark2.4版本不支持,并且使用时,
     * 必须在spark配置中加入spark.sql.extensions属性,
     * 其值为:org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions,在添加分区时还支持分区转换,语法如下:
     *     添加分区语法:ALTER TABLE ... ADD PARTITION FIELD
     *    删除分区语法:ALTER TABLE ... DROP PARTITION FIELD
     *
     */

    val spark: SparkSession = SparkSession
      .builder()
      .appName("SparkOperateIceberg")
      //指定hive catalog, catalog名称为hive_prod
      .config("spark.sql.catalog.hive_prod", "org.apache.iceberg.spark.SparkCatalog")
      .config("spark.sql.catalog.hive_prod.type", "hive")
      .config("spark.sql.catalog.hive_prod.uri", "thrift://master:9083")
      .config("iceberg.engine.hive.enabled", "true")
      // 将 loc 列添加成分区,必须添加
      .config("spark.sql.extensions","org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions")
      .enableHiveSupport()
      .getOrCreate()


    //1.创建普通表
    spark.sql(
      """
        | create table if not exists hive_prod.iceberg.repartition1
        | (id int,name string,loc string,ts timestamp) using iceberg
        |
  """.stripMargin)
    //2.向表中插入数据,并查询
    spark.sql(
      """
        |insert into hive_prod.iceberg.repartition1 values
        |(1,'zs',"beijing",cast(1608469830 as timestamp)),
        |(3,'ww',"shanghai",cast(1603096230 as timestamp))
        |
      """.stripMargin)

    spark.sql("select * from hive_prod.iceberg.repartition1").show()


    //3.将 loc 列添加成分区,必须添加 config("spark.sql.extensions",
    // "org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions") 配置
    spark.sql(
      """
        |alter table hive_prod.iceberg.repartition1 add partition field loc
        |
  """.stripMargin)

    //4.向表 mytbl中继续插入数据,之前数据没有分区,之后数据有分区
    spark.sql(
      """
        |insert into hive_prod.iceberg.repartition1 values
        |(5,'tq',"hangzhou",cast(1608279630 as timestamp)),
        |(6,'xx',"hangzhou",cast(1608279631 as timestamp)),
        |(2,'ls',"shandong",cast(1634559632 as timestamp))
        |
      """.stripMargin )

    spark.sql("select * from hive_prod.iceberg.repartition1").show()

    //spark 提交任务的命令
    //spark-submit --master yarn --class com.shujia.spark.iceberg.AlterTablePartition spark-1.0.jar
  }
}

  1. 将ts列进行转换作为分区列,插入数据并查询
//5.将 ts 列通过分区转换添加为分区列
spark.sql(
  """
    |alter table hadoop_prod.default.mytbl add partition field years(ts)
  """.stripMargin)

//6.向表 mytbl中继续插入数据,之前数据没有分区,之后数据有分区
spark.sql(
  """
    |insert into hadoop_prod.default.mytbl values
    |(4,'ml',"beijing",cast(1639920630 as timestamp)),
    |(6,'gb',"tianjin",cast(1576843830 as timestamp))
  """.stripMargin )
spark.sql("select * from hadoop_prod.default.mytbl").show()

在HDFS中数据存储和结果如下:

我的测试,在一级分区的基础上再次添加分区

测试代码:

package com.shujia.spark.iceberg

import org.apache.spark.sql.SparkSession

object AlterTable2Partitions {
  def main(args: Array[String]): Unit = {

    val spark: SparkSession = SparkSession
      .builder()
      .appName("SparkOperateIceberg")
      //指定hive catalog, catalog名称为hive_prod
      .config("spark.sql.catalog.hive_prod", "org.apache.iceberg.spark.SparkCatalog")
      .config("spark.sql.catalog.hive_prod.type", "hive")
      .config("spark.sql.catalog.hive_prod.uri", "thrift://master:9083")
      .config("iceberg.engine.hive.enabled", "true")
      // 将 loc 列添加成分区,必须添加
      .config("spark.sql.extensions","org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions")
      .enableHiveSupport()
      .getOrCreate()


    //5.将 ts 列通过分区转换添加为分区列
    spark.sql(
      """
        |alter table hive_prod.iceberg.repartition1 add partition field years(ts)
  """.stripMargin)

    //6.向表 mytbl中继续插入数据,之前数据没有分区,之后数据有分区
    spark.sql(
      """
        |insert into hive_prod.iceberg.repartition1 values
        |(4,'ml',"beijing",cast(1639920630 as timestamp)),
        |(4,'mm',"beijing",cast(1639920639 as timestamp)),
        |(6,'gb',"tianjin",cast(1576843830 as timestamp))
        |
      """.stripMargin )


    spark.sql("select * from hive_prod.iceberg.repartition1").show()

    //spark 提交任务的命令
    //spark-submit --master yarn --class com.shujia.spark.iceberg.AlterTable2Partitions spark-1.0.jar
  }
}

  1. 删除分区loc
//7.删除表 mytbl 中的loc分区
spark.sql(
  """
    |alter table hadoop_prod.default.mytbl drop partition field loc
  """.stripMargin)
//8.继续向表 mytbl 中插入数据,并查询
spark.sql(
  """
    |insert into hadoop_prod.default.mytbl values
    |(4,'ml',"beijing",cast(1639920630 as timestamp)),
    |(6,'gb',"tianjin",cast(1576843830 as timestamp))
  """.stripMargin )
spark.sql("select * from hadoop_prod.default.mytbl").show()

在HDFS中数据存储和结果如下:

注意:由于表中还有ts分区转换之后对应的分区,所以继续插入的数据loc分区为null

我的测试

测试代码:

package com.shujia.spark.iceberg

import org.apache.spark.sql.SparkSession

object DeleteTablePartition {
  def main(args: Array[String]): Unit = {

    /**
     *
     * 删除一个分区
     *
     */
    val spark: SparkSession = SparkSession
      .builder()
      .appName("SparkOperateIceberg")
      //指定hive catalog, catalog名称为hive_prod
      .config("spark.sql.catalog.hive_prod", "org.apache.iceberg.spark.SparkCatalog")
      .config("spark.sql.catalog.hive_prod.type", "hive")
      .config("spark.sql.catalog.hive_prod.uri", "thrift://master:9083")
      .config("iceberg.engine.hive.enabled", "true")
      // 将 loc 列添加成分区,必须添加
      .config("spark.sql.extensions","org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions")
      .enableHiveSupport()
      .getOrCreate()

    //7.删除表 mytbl 中的loc分区
    spark.sql(
      """
        |alter table hive_prod.iceberg.repartition1 drop partition field loc
  """.stripMargin)
    //8.继续向表 mytbl 中插入数据,并查询
    spark.sql(
      """
        |insert into hive_prod.iceberg.repartition1 values
        |(4,'ml',"beijing",cast(1639920630 as timestamp)),
        |(6,'gb',"tianjin",cast(1576843830 as timestamp))
        |
  """.stripMargin )

    spark.sql("select * from hive_prod.iceberg.repartition1").show()
    //spark 提交任务的命令
    //spark-submit --master yarn --class com.shujia.spark.iceberg.DeleteTablePartition spark-1.0.jar
  }
}

  1. 删除分区years(ts)
//9.删除表 mytbl 中的years(ts) 分区
spark.sql(
  """
    |alter table hadoop_prod.default.mytbl drop partition field years(ts)
  """.stripMargin)
//10.继续向表 mytbl 中插入数据,并查询
spark.sql(
  """
    |insert into hadoop_prod.default.mytbl values
    |(5,'tq',"hangzhou",cast(1608279630 as timestamp)),
    |(2,'ls',"shandong",cast(1634559630 as timestamp))
  """.stripMargin )
spark.sql("select * from hadoop_prod.default.mytbl").show()

在HDFS中数据存储和结果如下:

我的测试:

测试代码:

package com.shujia.spark.iceberg

import org.apache.spark.sql.SparkSession

object DeleteTable2Partitions {
  def main(args: Array[String]): Unit = {

    /**
     *
     * 删除一个分区之后再次删除一个分区
     *
     */
    val spark: SparkSession = SparkSession
      .builder()
      .appName("SparkOperateIceberg")
      //指定hive catalog, catalog名称为hive_prod
      .config("spark.sql.catalog.hive_prod", "org.apache.iceberg.spark.SparkCatalog")
      .config("spark.sql.catalog.hive_prod.type", "hive")
      .config("spark.sql.catalog.hive_prod.uri", "thrift://master:9083")
      .config("iceberg.engine.hive.enabled", "true")
      // 将 loc 列添加成分区,必须添加
      .config("spark.sql.extensions", "org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions")
      .enableHiveSupport()
      .getOrCreate()

    //9.删除表 mytbl 中的years(ts) 分区
    spark.sql(
      """
        |alter table hive_prod.iceberg.repartition1 drop partition field years(ts)
  """.stripMargin)
    //10.继续向表 mytbl 中插入数据,并查询
    spark.sql(
      """
        |insert into hive_prod.iceberg.repartition1 values
        |(5,'tq',"hangzhou",cast(1608279630 as timestamp)),
        |(2,'ls',"shandong",cast(1634559630 as timestamp))
  """.stripMargin )
    spark.sql("select * from hive_prod.iceberg.repartition1").show()


    //spark 提交任务的命令
    //spark-submit --master yarn --class com.shujia.spark.iceberg.DeleteTable2Partitions spark-1.0.jar
  }
  }

### 如何在Greenplum数据库中添加二级分区 在Greenplum数据库中实现多级分区(如一级和二级分区),可以通过创建带有子表的范围或列表分区来完成。对于已经存在的表,如果希望为其增加新的分区层次,则需要通过一系列SQL命令操作。 #### 创建带有一级和二级分区的新表 当定义新表时可以直接指定其为具有多个级别的分区结构: ```sql CREATE TABLE sales ( trans_id int, date date, amount decimal(10,2), region text ) DISTRIBUTED BY (trans_id) PARTITION BY RANGE (date) SUBPARTITION BY LIST (region) ( PARTITION p_2023 START ('2023-01-01') END ('2024-01-01') ( SUBPARTITION us VALUES ('US'), SUBPARTITION eu VALUES ('EU'), SUBPARTITION apac VALUES ('APAC') ), DEFAULT PARTITION extra ); ``` 此脚本创建了一个名为`sales`的一级按日期范围划分、二级按照地区列表进一步细分的数据表[^1]。 #### 对现有表添加二级分区 要向现有的已分区表添加额外的次级分区,通常涉及几个步骤:首先确保该表支持这种类型的扩展;其次可能需要先删除旧版本中的数据并重新导入到更新后的模式下。然而,在某些情况下也可以利用`ALTER TABLE ... ADD PARTITION`语句直接修改当前架构而无需完全重建整个表格。 假设有一个基于年份的一级分区表,并想要在此基础上加入季度作为第二层分类方式之一: ```sql -- 增加一个新的年度区间以及对应的四个季度子分区 ALTER TABLE yearly_sales_data ADD PARTITION year_2023 start('2023-01-01') end('2024-01-01') SPLIT AT ('2023-04-01', '2023-07-01', '2023-10-01'); -- 或者单独为某一年度内的特定时间段新增季度级别分区 ALTER TABLE yearly_sales_data EXCHANGE PARTITION FOR (RANK(2)) WITH TABLE qtr_two; ``` 上述例子展示了两种不同的方法用于引入更细粒度的时间维度上的组织形式——要么是在建立之初就规划好所有必要的分片,要么事后动态调整以适应变化的需求[^3]。 需要注意的是,具体实施细节可能会因所使用的Greenplum版本不同有所差异,请参照官方文档获取最准确的操作指南。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值