问题描述
我在尝试创建固定宽度表格时遇到此错误。 前 7 个占位符用于第一列,后跟一个空格,然后是从第 9 位开始的第二列。
1 1050174
1 1050175
1 1050177
1 1050178
2 1050180
2 1050181
1 1050187
1 1050188
1 1050189
我收到此错误:
HIVE_SERDE_NOT_FOUND:解串器不存在: org.apache.hadoop.hive.contrib.serde2.regexserde
这个create table语句不会失败,而是在选择数据时显示上面提到的错误。
CREATE EXTERNAL TABLE IF NOT EXISTS hunspell.frequency1(
`count` string,`word` string
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.regexserde'
WITH SERDEPROPERTIES ("input.regex" = "(.{7})(.{100})" ) LOCATION 's3://hunspell/frequency/'
更新:
此测试表按预期工作。它提取第一、第二和第五列。
CREATE EXTERNAL TABLE hunspell.citiesr1 (id int,city_org string,ppl float)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.regexserde'
WITH SERDEPROPERTIES ('input.regex'='^(\\d+)\\t([^\\t]*)\\t\\S+\\t\\S+\\t(\\d++.\\d++).*') LOCATION 's3://hunspell/myserde/';
数据如下:
1 東京 Tokyo Japan 33.8
2 大阪 Osaka Japan 16.7
11 北京 Beijing China 13.2
12 廣州 Guangzhou China 15.3
21 Αθηνα athens Greece 3.7
31 Якутск Yakutsk Russia 0.6
110 La Coruña Corunna Spain 0.37
112 Cádiz Cadiz Spain 0.4
120 Köln Cologne Germany 0.97
121 München Munich Germany 1.2
130 Tårnby Tarnby Danmark 0.04
140 Tønsberg Tonsberg norway 0.05
150 Besançon Bisanz France 0.12
上面发布的示例数据使用制表符作为分隔符。我的文件不是由制表符分隔的。假设前 4 个字符是频率,接下来的 10 个字符是 ID,后面可能跟也可能不跟 100 个字符的名称。
1 1050174
1 1050175
1 1050177
换句话说,我如何使用正则表达式 serde 在 Athena 中导入固定宽度的数据?
更新 2:
感谢回答,我可以使用这个导入数据:
CREATE EXTERNAL TABLE `frequency`(
`count` string,`word` string)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.regexserde'
WITH SERDEPROPERTIES ('input.regex'='^(.{7}) (.+)$')
LOCATION 's3://XunspellX/stack/';
是否可以将第一列“计数”为整数?如果我只是将第一列类型更改为整数,Athena 不会导入任何内容。
解决方法
您在问题的第一部分收到错误消息,因为您使用的是 Athena 不支持的 SerDe。
HIVE_SERDE_NOT_FOUND:反序列化器不存在:org.apache.hadoop.hive.contrib.serde2.RegexSerDe
Athena docs 列出了支持的 SerDes,因此对于正则表达式,您将使用 org.apache.hadoop.hive.serde2.RegexSerDe
,正如您稍后发现的那样。
对于基于长度解析列,您应该能够根据需要修改您的正则表达式模式。以下是基于您提供的示例数据和描述的一些不同示例。
场景 1
两个以空格分隔的数字列,可能带有前导和/或尾随空格。
1 1050174
1 1050175
1 1050177
模式:/^ *(\d+) (\d+) *$/gm
场景 2
前 7 个占位符用于第一列,后跟一个空格 然后是从第 9 位开始的第二列
0000001 105017434786
0000002 105013
0000003 1050177438
模式:/^(\d{7}) (\d+)$/gm
场景 3
我的文件不是由制表符分隔的。让我们假设前 4 个字符 是频率,接下来的 10 个是 ID,后面可能跟着也可能不跟着 100个字符的名称
假设在这种情况下,您的数据不像其他两个示例那样由空格分隔,并且第三列可以为空且最大长度为 100,您可能会得到如下结果:
00201050174347some-nullable-third-column-value
01931050174348
19841050174349another-nullable-third-column-value
模式:/^(\d{4})(\d{10})(.{0,100})$/gm
最后,将所有内容放在一起,您将有一个 create table 语句,对于第三种情况,它看起来像这样:
CREATE EXTERNAL TABLE sample_database.sample_data (frequency int,id bigint,description varchar(100))
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES ('input.regex'='^(\\d{4})(\\d{10})(.{0,100})$')
LOCATION 's3://your-s3-bucket/';
请注意此处正则表达式模式中的双反斜杠。每this doc:
注意:RegexSerDe 遵循 Java 标准。因为反斜杠是 Java String 类中的转义字符,所以必须使用双反斜杠来定义单反斜杠。例如,要定义 \w,您必须在正则表达式中使用 \w。
,根据用户fearerjon 的建议,以下查询按预期工作:
CREATE EXTERNAL TABLE `frequency`(
`count` int,`word` string)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES ('input.regex'='^ *(\\d+) (.+)$')
LOCATION 's3://XunspelX/stack/';