如何将带有 NULL 值的引用 CSV 读入 Amazon Athena
How to read quoted CSV with NULL values into Amazon Athena
我正在尝试使用存储在 S3 上的引用 CSV 文件在 Athena 中创建外部 table。问题是,我的 CSV 包含列中的缺失值,这些值应该被读取为 INT。简单示例:
CSV:
id,height,age,name
1,,26,"Adam"
2,178,28,"Robert"
创建 TABLE 定义:
CREATE EXTERNAL TABLE schema.test_null_unquoted (
id INT,
height INT,
age INT,
name STRING
)
ROW FORMAT
SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES (
'separatorChar' = ",",
'quoteChar' = '"',
'skip.header.line.count' = '1'
)
STORED AS TEXTFILE
LOCATION 's3://mybucket/test_null/unquoted/'
CREATE TABLE
语句运行良好,但当我尝试查询 table 时,我得到 HIVE_BAD_DATA: Error parsing field value ''
.
我试着让 CSV 看起来像这样(引用空字符串):
"id","height","age","name"
1,"",26,"Adam"
2,178,28,"Robert"
但它不起作用。
尝试在 SERDEPROPERTIES
中指定 'serialization.null.format' = ''
- 无效。
尝试通过 TBLPROPERTIES ('serialization.null.format'='')
指定相同的内容 - 仍然没有。
当您将所有列指定为 STRING
时,它会起作用,但这不是我需要的。
因此,问题是,是否有 任何方法 以正确的列规范将引用的 CSV(引用很重要,因为我的真实数据要复杂得多)读取到 Athena?
处理这些数据的快捷方式:
CSV:
id,height,age,name
1,,26,"Adam"
2,178,28,"Robert"
3,123,34,"Bill, Comma"
4,183,38,"Alex"
DDL:
CREATE EXTERNAL TABLE Whosebug.test_null_unquoted (
id INT,
height INT,
age INT,
name STRING
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n' -- Or use Windows Line Endings
LOCATION 's3://XXXXXXXXXXXXX/'
TBLPROPERTIES ('skip.header.line.count'='1')
;
问题是它没有处理最后一个字段中的引号字符。基于 AWS, this makes sense as the LazySimpleSerDe given the following from Hive 提供的文档。
我怀疑解决方案正在使用以下 SerDe org.apache.hadoop.hive.serde2.RegexSerDe
。
我稍后会研究正则表达式。
编辑:
承诺的正则表达式:
CREATE EXTERNAL TABLE Whosebug.test_null_unquoted (
id INT,
height INT,
age INT,
name STRING
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
"input.regex" = "(.*),(.*),(.*),\"(.*)\""
)
LOCATION 's3://XXXXXXXXXXXXXXX/'
TBLPROPERTIES ('skip.header.line.count'='1') -- Does not appear to work
;
注意:RegexSerDe
似乎无法与 TBLPROPERTIES ('skip.header.line.count'='1')
一起正常工作。这可能是由于 Athena 或 SerDe 使用的 Hive version。在您的情况下,您可能只排除 ID IS NULL
处的行。
进一步阅读:
遗憾的是,无法在 Athena 中获得对引用字段 和 对空值的支持。您必须选择或。
您可以使用 OpenCSVSerDe 并将所有列键入为字符串,这将为您提供对带引号的字段的支持,以及对空字段的 emtpty 字符串。使用 TRY_CAST
或 CASE/WHEN
.
在查询时转换值
或者您可以使用 LazySimpleSerDe
并在查询时去掉引号。
我会选择 OpenCSVSerDe,因为您始终可以创建具有所有类型转换的视图,并将该视图用于您的常规查询。
您可以在此处阅读在 Athena 中使用 CSV 的所有细节:The Athena Guide: Working with CSV
这对我有用。使用 OpenCSVSerDe 并将所有列转换为字符串。阅读更多:https://aws.amazon.com/premiumsupport/knowledge-center/athena-hive-bad-data-error-csv/
我正在尝试使用存储在 S3 上的引用 CSV 文件在 Athena 中创建外部 table。问题是,我的 CSV 包含列中的缺失值,这些值应该被读取为 INT。简单示例:
CSV:
id,height,age,name
1,,26,"Adam"
2,178,28,"Robert"
创建 TABLE 定义:
CREATE EXTERNAL TABLE schema.test_null_unquoted (
id INT,
height INT,
age INT,
name STRING
)
ROW FORMAT
SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES (
'separatorChar' = ",",
'quoteChar' = '"',
'skip.header.line.count' = '1'
)
STORED AS TEXTFILE
LOCATION 's3://mybucket/test_null/unquoted/'
CREATE TABLE
语句运行良好,但当我尝试查询 table 时,我得到 HIVE_BAD_DATA: Error parsing field value ''
.
我试着让 CSV 看起来像这样(引用空字符串):
"id","height","age","name"
1,"",26,"Adam"
2,178,28,"Robert"
但它不起作用。
尝试在 SERDEPROPERTIES
中指定 'serialization.null.format' = ''
- 无效。
尝试通过 TBLPROPERTIES ('serialization.null.format'='')
指定相同的内容 - 仍然没有。
当您将所有列指定为 STRING
时,它会起作用,但这不是我需要的。
因此,问题是,是否有 任何方法 以正确的列规范将引用的 CSV(引用很重要,因为我的真实数据要复杂得多)读取到 Athena?
处理这些数据的快捷方式:
CSV:
id,height,age,name
1,,26,"Adam"
2,178,28,"Robert"
3,123,34,"Bill, Comma"
4,183,38,"Alex"
DDL:
CREATE EXTERNAL TABLE Whosebug.test_null_unquoted (
id INT,
height INT,
age INT,
name STRING
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n' -- Or use Windows Line Endings
LOCATION 's3://XXXXXXXXXXXXX/'
TBLPROPERTIES ('skip.header.line.count'='1')
;
问题是它没有处理最后一个字段中的引号字符。基于 AWS, this makes sense as the LazySimpleSerDe given the following from Hive 提供的文档。
我怀疑解决方案正在使用以下 SerDe org.apache.hadoop.hive.serde2.RegexSerDe
。
我稍后会研究正则表达式。
编辑:
承诺的正则表达式:
CREATE EXTERNAL TABLE Whosebug.test_null_unquoted (
id INT,
height INT,
age INT,
name STRING
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
"input.regex" = "(.*),(.*),(.*),\"(.*)\""
)
LOCATION 's3://XXXXXXXXXXXXXXX/'
TBLPROPERTIES ('skip.header.line.count'='1') -- Does not appear to work
;
注意:RegexSerDe
似乎无法与 TBLPROPERTIES ('skip.header.line.count'='1')
一起正常工作。这可能是由于 Athena 或 SerDe 使用的 Hive version。在您的情况下,您可能只排除 ID IS NULL
处的行。
进一步阅读:
遗憾的是,无法在 Athena 中获得对引用字段 和 对空值的支持。您必须选择或。
您可以使用 OpenCSVSerDe 并将所有列键入为字符串,这将为您提供对带引号的字段的支持,以及对空字段的 emtpty 字符串。使用 TRY_CAST
或 CASE/WHEN
.
或者您可以使用 LazySimpleSerDe
并在查询时去掉引号。
我会选择 OpenCSVSerDe,因为您始终可以创建具有所有类型转换的视图,并将该视图用于您的常规查询。
您可以在此处阅读在 Athena 中使用 CSV 的所有细节:The Athena Guide: Working with CSV
这对我有用。使用 OpenCSVSerDe 并将所有列转换为字符串。阅读更多:https://aws.amazon.com/premiumsupport/knowledge-center/athena-hive-bad-data-error-csv/