Hive分区表修改(增删)列

这篇具有很好参考价值的文章主要介绍了Hive分区表修改(增删)列。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、环境及测试数据

环境:CDH6.3.0,Hive 2.1.1-cdh6.3.0

基础数据分区表test1,包含a,b,c,d共4列加分区列p_day,向其中插入两行数据

create table test1(a int,b bigint,c float,d string) partitioned by(p_day string) stored as parquet;

insert into test1 partition(p_day) values(1,11,1.1,'str1','2022-11-19'),(2,22,2.2,'str2','2022-11-19');

表中数据及parquet文件信息如下:

0: jdbc:hive2://dev-master1:10000 > select * from test1;
+----------+----------+----------+----------+--------------+
| test1.a  | test1.b  | test1.c  | test1.d  | test1.p_day  |
+----------+----------+----------+----------+--------------+
| 1        | 11       | 1.1      | str1     | 2022-11-19   |
| 2        | 22       | 2.2      | str2     | 2022-11-19   |
+----------+----------+----------+----------+--------------+
[hive@dev-master1 tmp]$ hdfs dfs -get /user/hive/warehouse/debug_test.db/test1/p_day=2022-11-19/000000_0 ./
[hive@dev-master1 tmp]$ parquet-tools schema 000000_0
message hive_schema {
  optional int32 a;
  optional int64 b;
  optional float c;
  optional binary d (STRING);
}

[hive@dev-master1 tmp]$ parquet-tools cat 000000_0
a = 1
b = 11
c = 1.1
d = str1

a = 2
b = 22
c = 2.2
d = str2

二、 删除列

2.1 测试表test2

create table test2(b bigint,a int,c float) partitioned by(p_day string) stored as parquet;

test2表直接使用test1表的文件:

[hive@dev-master1 tmp]$ hdfs dfs -mkdir /user/hive/warehouse/debug_test.db/test2/p_day=2022-11-19
[hive@dev-master1 tmp]$ hdfs dfs -cp /user/hive/warehouse/debug_test.db/test1/p_day=2022-11-19/000000_0 /user/hive/warehouse/debug_test.db/test2/p_day=2022-11-19/

修复分区并查询数据

msck repair table test2;
select * from test2;
+----------+----------+----------+--------------+
| test2.b  | test2.a  | test2.c  | test2.p_day  |
+----------+----------+----------+--------------+
| 11       | 1        | 1.1      | 2022-11-19   |
| 22       | 2        | 2.2      | 2022-11-19   |
+----------+----------+----------+--------------+

2.2 DDL删除列?

删除test2表的a列,看起来只有通过replace columns实现,但是运行报错,根据官方文档,只有表的序列化方式为native SerDe(DynamicSerDe, MetadataTypedColumnsetSerDe, LazySimpleSerDe and ColumnarSerDe)才能执行。

0: jdbc:hive2://dev-master1:10000> alter table test2 replace columns(b bigint,c float);
INFO  : Compiling command(queryId=hive_20221119180121_23e7971f-7b2f-4693-90b9-469ec44a97bd): alter table test2 replace columns(b bigint,c float)
INFO  : Semantic Analysis Completed
INFO  : Returning Hive schema: Schema(fieldSchemas:null, properties:null)
INFO  : Completed compiling command(queryId=hive_20221119180121_23e7971f-7b2f-4693-90b9-469ec44a97bd); Time taken: 1.479 seconds
INFO  : Executing command(queryId=hive_20221119180121_23e7971f-7b2f-4693-90b9-469ec44a97bd): alter table test2 replace columns(b bigint,c float)
INFO  : Starting task [Stage-0:DDL] in serial mode
ERROR : FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. Replacing columns cannot drop columns for table debug_test.test2. SerDe may be incompatible
INFO  : Completed executing command(queryId=hive_20221119180121_23e7971f-7b2f-4693-90b9-469ec44a97bd); Time taken: 0.018 seconds
Error: Error while processing statement: FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. Replacing columns cannot drop columns for table debug_test.test2. SerDe may be incompatible (state=42000,code=1)

2.3 代码连接Hive Metastore删除列

主要Maven依赖:

用代码连接Hive MetaStore修改可以成功:

package com.bigdata.databasetest.hive.metastore;

import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.hive.metastore.HiveMetaStoreClient;
import org.apache.hadoop.hive.metastore.api.FieldSchema;
import org.apache.hadoop.hive.metastore.api.Table;
import org.apache.thrift.TException;

import java.util.List;
import java.util.stream.Collectors;


/**
 * ClassName: HiveMetaStoreClientTest
 * Description:
 *
 * @author 0x3E6
 * @version 1.0.0
 * @date 2022/11/19 17:12
 */
public class HiveMetaStoreClientTest {

    public static void main(String[] args) throws TException {
        HiveConf hiveConf = new HiveConf();
        System.setProperty("HADOOP_USER_NAME", "hive");
        hiveConf.set(HiveConf.ConfVars.METASTOREURIS.varname, "thrift://dev-master1:9083");
        try (HiveMetaStoreClient client = new HiveMetaStoreClient(hiveConf)) {
            Table table = client.getTable("debug_test", "test2");
            List<FieldSchema> cols = table.getSd().getCols();
            cols = cols.stream().filter(fieldSchema -> !"a".equalsIgnoreCase(fieldSchema.getName())).collect(Collectors.toList());
            table.getSd().setCols(cols);
            client.alter_table("debug_test", "test2", table);
        }
    }
}

这样查询数据有问题,不论sql是否带分区:

select * from test2;
select * from test2 where p_day='2022-11-19';

查询结果为:

+----------+----------+--------------+
| test2.b  | test2.c  | test2.p_day  |
+----------+----------+--------------+
| 11       | NULL     | 2022-11-19   |
| 22       | NULL     | 2022-11-19   |
+----------+----------+--------------+

因为只改了表的元数据,而未改分区的元数据。

0: jdbc:hive2://dev-master1:10000> desc test2;
+--------------------------+-----------------------+-----------------------+
|         col_name         |       data_type       |        comment        |
+--------------------------+-----------------------+-----------------------+
| b                        | bigint                |                       |
| c                        | float                 |                       |
| p_day                    | string                |                       |
|                          | NULL                  | NULL                  |
| # Partition Information  | NULL                  | NULL                  |
| # col_name               | data_type             | comment               |
|                          | NULL                  | NULL                  |
| p_day                    | string                |                       |
+--------------------------+-----------------------+-----------------------+
0: jdbc:hive2://dev-master1:10000> desc test2 partition(p_day='2022-11-19');
+--------------------------+-----------------------+-----------------------+
|         col_name         |       data_type       |        comment        |
+--------------------------+-----------------------+-----------------------+
| b                        | bigint                |                       |
| a                        | int                   |                       |
| c                        | float                 |                       |
| p_day                    | string                |                       |
|                          | NULL                  | NULL                  |
| # Partition Information  | NULL                  | NULL                  |
| # col_name               | data_type             | comment               |
|                          | NULL                  | NULL                  |
| p_day                    | string                |                       |
+--------------------------+-----------------------+-----------------------+

具体原理及原因还未分析,但可以修复,只需要保持分区的列与表的列顺序一致,无法执行REPLACE COLUMNS语句,通过CHANGE COLUMNS语句将c列移动到a列之前:

alter table test2 partition(p_day='2022-11-19') change column c c float after b;
select * from test2 where p_day='2022-11-19';
+----------+----------+--------------+
| test2.b  | test2.c  | test2.p_day  |
+----------+----------+--------------+
| 11       | 1.1      | 2022-11-19   |
| 22       | 2.2      | 2022-11-19   |
+----------+----------+--------------+

2.3.1 同时更新表与分区元数据

ALTER TABLE语句可以添加CASCADE,更新表元数据的同时级联更新分区元数据,Hive MetaStoreClient API也可以使用带CASCADE的方法,前面的代码调用的HiveMetaStoreClient的alter_table(String dbname, String tbl_name, Table new_tbl)方法,可以调用alter_table(String defaultDatabaseName, String tblName, Table table, boolean cascade)方法,新建表test3与test2结构一致,也同样把test1的数据拷贝到表test3,再通过代码删除表test3的列a:

package com.bigdata.databasetest.hive.metastore;

import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.hive.metastore.HiveMetaStoreClient;
import org.apache.hadoop.hive.metastore.api.FieldSchema;
import org.apache.hadoop.hive.metastore.api.Table;
import org.apache.thrift.TException;

import java.util.List;
import java.util.stream.Collectors;


/**
 * ClassName: HiveMetaStoreClientTest
 * Description:
 *
 * @author 0x3E6
 * @version 1.0.0
 * @date 2022/11/19 17:12
 */
public class HiveMetaStoreClientTest {

    public static void main(String[] args) throws TException {
        HiveConf hiveConf = new HiveConf();
        System.setProperty("HADOOP_USER_NAME", "hive");
        hiveConf.set(HiveConf.ConfVars.METASTOREURIS.varname, "thrift://dev-master1:9083");
        try (HiveMetaStoreClient client = new HiveMetaStoreClient(hiveConf)) {
            Table table = client.getTable("debug_test", "test3");
            List<FieldSchema> cols = table.getSd().getCols();
            cols = cols.stream().filter(fieldSchema -> !"a".equalsIgnoreCase(fieldSchema.getName())).collect(Collectors.toList());
            table.getSd().setCols(cols);
//            client.alter_table("debug_test", "test2", table);
            client.alter_table("debug_test", "test3", table, true);
        }
    }
}

更新后表test3可正常查询:

0: jdbc:hive2://dev-master1:10000> select * from test3;
+----------+----------+--------------+
| test3.b  | test3.c  | test3.p_day  |
+----------+----------+--------------+
| 11       | 1.1      | 2022-11-19   |
| 22       | 2.2      | 2022-11-19   |
+----------+----------+--------------+

表与分区元数据也相同:

0: jdbc:hive2://dev-master1:10000> desc test3;
+--------------------------+-----------------------+-----------------------+
|         col_name         |       data_type       |        comment        |
+--------------------------+-----------------------+-----------------------+
| b                        | bigint                |                       |
| c                        | float                 |                       |
| p_day                    | string                |                       |
|                          | NULL                  | NULL                  |
| # Partition Information  | NULL                  | NULL                  |
| # col_name               | data_type             | comment               |
|                          | NULL                  | NULL                  |
| p_day                    | string                |                       |
+--------------------------+-----------------------+-----------------------+
0: jdbc:hive2://dev-master1:10000> desc test3 partition(p_day='2022-11-19');
+--------------------------+-----------------------+-----------------------+
|         col_name         |       data_type       |        comment        |
+--------------------------+-----------------------+-----------------------+
| b                        | bigint                |                       |
| c                        | float                 |                       |
| p_day                    | string                |                       |
|                          | NULL                  | NULL                  |
| # Partition Information  | NULL                  | NULL                  |
| # col_name               | data_type             | comment               |
|                          | NULL                  | NULL                  |
| p_day                    | string                |                       |
+--------------------------+-----------------------+-----------------------+

三、添加列

根据Hive文档,可通过ADD COLUMNS语句添加列,ADD COLUMNS语句会将指定的列添加到(除分区列外)其他列后面。

ALTER TABLE table_name 
  [PARTITION partition_spec]                 -- (Note: Hive 0.14.0 and later)
  ADD|REPLACE COLUMNS (col_name data_type [COMMENT col_comment], ...)
  [CASCADE|RESTRICT]                         -- (Note: Hive 1.1.0 and later)

如果使用Hive MetaStoreClient API不小心将列加到了(除分区列)外其他列之间,且造成了表与分区列顺序不同,也可结合CHANGE COLUMNS语句修改表或分区的列顺序恢复即可:

ALTER TABLE table_name [PARTITION partition_spec] CHANGE [COLUMN] col_old_name col_new_name column_type
  [COMMENT col_comment] [FIRST|AFTER column_name] [CASCADE|RESTRICT];

结论

可以通过Hive MetaStoreClient API增删Hive列,但必须保持Hive表与各分区元数据的列顺序一致。文章来源地址https://www.toymoban.com/news/detail-425715.html

参考链接

  • Hive LanguageManual DDL
  • Parquet格式表重命名列名后Hive查询列数据显示NULL异常分析
  • Java调用Hive-metastore接口

到了这里,关于Hive分区表修改(增删)列的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【DolphinScheduler】datax读取hive分区表时,空分区、分区无数据任务报错问题解决

    最近在使用海豚调度DolphinScheduler的Datax组件时,遇到这么一个问题:之前给客户使用海豚做的离线数仓的分层搭建,一直都运行好好的,过了个元旦,这几天突然在数仓做任务时报错,具体报错信息如下: com.alibaba.datax.common.exception.DataXException: Code:[HdfsReader-08], Description:[您尝

    2024年01月16日
    浏览(64)
  • Hive数据加载方式(load、insert;普通表、分区表)

    介绍 Hive 数据加载方式(insert、load) 基础语法: load data [local] inpath \\\'/opt/module/datas/student.txt\\\' [overwrite] into table student[partition ] 参数说明: 1 load data: 表示加载数据 2 local: 表示从本地加载数据到 hive 表;否则从 HDFS 加载数据到 hive 表 3 inpath: 表示加载数据的路径 相对路径,例如

    2024年02月03日
    浏览(52)
  • 大数据开发之Hive(查询、分区表和分桶表、函数)

    1、查询语句语法 2、书写次序和执行次序 顺序 书写次序 书写次序说明 执行次序 执行次序说明 1 select 查询 from 先执行表与表直接的关系 2 from 先执行表与表直接的关系 on 先执行表与表直接的关系 3 join on 先执行表与表直接的关系 join 先执行表与表直接的关系 4 where 先执行表

    2024年01月17日
    浏览(48)
  • hive分区表 静态分区和动态分区

    现有数据文件 data_file 如下: 2023-08-01,Product A,100.0 2023-08-05,Product B,150.0 2023-08-10,Product A,200.0 需要手动指定分区 现有源数据表如下: CREATE TABLE sales_source (     sale_date STRING,     product STRING,     amount DOUBLE ); INSERT INTO sales_source VALUES     (\\\'2023-08-01\\\', \\\'Product A\\\', 100.0),     (\\\'2023-08-

    2024年02月10日
    浏览(46)
  • Hive分区表实战 - 多分区字段

    本实战教程通过一系列Hive SQL操作,演示了如何在大数据环境下创建具有省市分区的大学表,并从本地文件系统加载不同地区的学校数据到对应分区。首先,创建名为 school 的数据库并切换至该数据库;接着,在数据库中定义一个名为 university 的分区表,其结构包括ID和名称两

    2024年01月15日
    浏览(42)
  • HIVE创建分区表

    partitioned by ( c2 string ) # 创建分区 c1跟c2都是字段,但是创建的时候不能写在t2里面,只能写在分区里面(同时select查询的时候,c2的字段也要写在最后面) 要加载数据到分区表,只需在原来的加载数据的语句上增加partition,同时指定分区的字段值即可。 注意:当你退出

    2024年02月15日
    浏览(38)
  • Hive 分区表新增字段 cascade

    在以前上线的分区表中新加一个字段,并且要求添加到指定的位置列。 加 cascade 操作 创建测试表 插入测试数据 查看现有数据 官网添加列的语法 注意: Hive 1.1.0 中有 CASCADE|RESTRICT 子句。 ALTER TABLE ADD|REPLACE COLUMNS CASCADE 命令修改表元数据的列,并将相同的更改级联到所有分区

    2024年02月11日
    浏览(51)
  • Hive ---- 分区表和分桶表

    Hive中的分区就是把一张大表的数据按照业务需要分散的存储到多个目录,每个目录就称为该表的一个分区。在查询时通过where子句中的表达式选择查询所需要的分区,这样的查询效率会提高很多。 1. 创建分区表 2. 分区表读写数据 1)写数据 (1)load 数据准备 在/opt/module/hiv

    2024年02月10日
    浏览(57)
  • Hive 分区表和分桶表

    在《Hive 建表语句解析》文章中,建表的时候我们可以使用 PARTITIONED BY 子句和 CLUSTERED BY 子句来创建分区表和分桶表,为什么要创建分区表和分桶表呢?分区表和分桶表有什么区别呢? 1. 为什么分区 在Hive 查询中一般会扫描整个表内容,会消耗很多时间做没必要的工作。有时

    2023年04月23日
    浏览(43)
  • 二次开发DataX以支持HIVE分区表

            最近在一个大数据的项目开发中使用到了数据同步工具DataX,但在使用过程中发现了DataX对HIve分区表的支持不太友好。         具体体现在将数据库中的数据同步到HIVE分区表时,写入目录为HIVE表分区为dt=XXXX,如果不提前创建该分区,会报目录不存在的错误,如

    2024年02月16日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包