如何将带有 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 for Processing CSV

遗憾的是,无法在 Athena 中获得对引用字段 对空值的支持。您必须选择或。

您可以使用 OpenCSVSerDe 并将所有列键入为字符串,这将为您提供对带引号的字段的支持,以及对空字段的 emtpty 字符串。使用 TRY_CASTCASE/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/