草庐IT

Hive表字段类型转换错误解决:Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask.

暴走的山芋 2024-01-07 原文

文章目录

1 问题场景

假设某有数据的Hive表temp_table的字段状况如下,需要将A字段由string类型转为int类型:

字段名称字段类型是否为分区字段
Astring
Bint
Cbigint
Dstring

1.1 问题发生的背景

在Hdfs数据库中,该表的数据是以Parquet文件格式存储的,包含多个分区。原本在该表中的字段A的类型为int。然而笔者误操作,将该字段的类型转换为了string,即前文所述的表字段状态。

笔者在查询时发现,用HiveSql查询不会报错,而用SparkSql查询本表时,会报如下错误信息:

org.apache.spark.sql.execution.QueryExecutionException: Parquet column cannot be converted in file [文件所在OSS路径]. Column: [has_explicit_source_keys], Expected: StringType, Found: INT32

错误的大致意思为文件中的字段类型和Hive元数据中的字段类型不同,且无法强制转换。
为了继续可以用spark查询本表,笔者尝试修复表字段类型。然而在修复表字段类型时,笔者发现以下两种方法都无法完成操作,并且会报错

1.1 操作方法1

使用如下语句修改Hive表的字段类型时。可能会发现字段可以从string转到Int,但不能从Int转回String。

ALTER TABLE temp_table CHANGE CLOUMN A A int;

1.2 操作方法2

  1. 删除要转换类型的字段A,使原表只剩B、C两个字段。
  2. 新增字段A,将类型转换为int。由于Hive建表时不允许指定列的位置,所以会添加在表的最后。
  3. 将字段A挪到第一位。本步会报错,不允许进行此操作。
-- Step1
ALTER TABLE temp_table replace COLUMNS (B int,C bigint);
-- Step2
ALTER TABLE temp_table ADD COLUMNS (A int);
-- Step3(本步会报错)
ALTER TABLE temp_table CHANGE CLOUMN A A int FIRST;

1.3 报错信息

FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. Unable to alter table. The following columns have types incompatible with the existing columns in their respective positions :
column_name

该错误的意思是,Hive表元数据中已有的字段类型无法被转换为新指定的字段类型。而且结合上述操作方法2可知,如果表中有数据,那么即便删除了某个字段,其字段类型仍然会保留在原来的位置上。

2 问题分析

查看官方文档后,可以了解到,列转换操作是由一个参数控制的:

hive.metastore.disallow.incompatible.col.type.changes 设置为 false 时,Metastore 中的列类型可以从任何类型更改为任何其他类型。 在执行类型更改后,如果新类型可以正确显示数据,则将显示数据。 否则,数据将显示为 NULL。

而hive.metastore.disallow.incompatible.col.type.changes这个参数,在Hive2.0后,默认为True。即在字段类型转换时,不再允许显式转换(强制转换),而是只能进行隐式转换,即由低级类型转换为高级类型。

关于隐式转换的规则Hive官方文档(需要翻墙后查看该链接)中的说明如下:

本例中的Hive版本为2.7.2

所以为了实现字段类型的显式转换,需要设置hive.metastore.disallow.incompatible.col.type.changes。

3 解决方法

特别注意:在某些环境下,前两种方法都不能使该参数生效,只能使用第三种方法

3.1 在SQL代码中加参数

在SQL代码最前方加入:set hive.metastore.disallow.incompatible.col.type.changes=false;

3.2 在提交Hive程序时,附加上hiveconf参数

3.3 修改 hive-site.xml文件

在hive 配置文件 hive-site.xml中添加或修改参数:

<property>
<name>hive.metastore.disallow.incompatible.col.type.changes</name>
<value>false</value>
</property>

修改参数之后,需要重启Hive服务才能使参数生效。重启Hive服务后,使用Hive查询该参数值,可以发现修改成功了

同时,可以在DDL语句修改Hive元数据中的字段类型时,实现显式转换。

有关Hive表字段类型转换错误解决:Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask.的更多相关文章

  1. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  2. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  3. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  4. ruby - 将数组的内容转换为 int - 2

    我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]

  5. ruby - 将散列转换为嵌套散列 - 2

    这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[

  6. ruby - Infinity 和 NaN 的类型是什么? - 2

    我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串

  7. ruby - 检查方法参数的类型 - 2

    我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)

  8. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

  9. ruby-on-rails - 如何在 Rails View 上显示错误消息? - 2

    我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c

  10. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

随机推荐