Hive 如何过滤进入AWS配置单元表的多行JSON数据

Hive 如何过滤进入AWS配置单元表的多行JSON数据,hive,amazon-emr,aws-iot,amazon-athena,amazon-kinesis-firehose,Hive,Amazon Emr,Aws Iot,Amazon Athena,Amazon Kinesis Firehose,我有一个AWS物联网规则,它将传入的JSON发送到Kinesis消防软管 我的物联网发布中的JSON数据都在一行中-例如: {"count":4950, "dateTime8601": "2017-03-09T17:15:28.314Z"} 管理员UI中的IoT“测试”部分允许您发布消息,默认为以下内容(注释格式的多行JSON): 我将消防水带流式传输到S3,然后由EMR转换为柱状格式,最终供雅典娜使用 问题是,在转换为列格式期间,配置单元(特别是)无法处理跨越多行的JSON对象。它会破坏转换

我有一个AWS物联网规则,它将传入的JSON发送到Kinesis消防软管

我的物联网发布中的JSON数据都在一行中-例如:

{"count":4950, "dateTime8601": "2017-03-09T17:15:28.314Z"}
管理员UI中的IoT“测试”部分允许您发布消息,默认为以下内容(注释格式的多行JSON):

我将消防水带流式传输到S3,然后由EMR转换为柱状格式,最终供雅典娜使用

问题是,在转换为列格式期间,配置单元(特别是)无法处理跨越多行的JSON对象。它会破坏转换,而不会转换好的、单行的JSON记录

我的问题是:

  • 如何设置FireHose以忽略多行JSON
  • 若不可能,如何告诉配置单元在加载到表中之前删除换行符,或者至少捕获异常并尝试继续
在定义配置单元表时,我已经尝试忽略格式错误的JSON:

DROP TABLE site_sensor_data_raw;
CREATE EXTERNAL TABLE site_sensor_data_raw (
 count int,     
 dateTime8601 timestamp
)
PARTITIONED BY(year int, month int, day int, hour int)
ROW FORMAT  serde 'org.apache.hive.hcatalog.data.JsonSerDe'
with serdeproperties (
 'ignore.malformed.json' = 'true',
 "timestamp.formats"="yyyy-MM-dd'T'HH:mm:ss.SSS'Z',millis"
)
LOCATION 's3://...';
以下是我的完整HQL,用于进行转换:

--Example of converting to OEX/columnar formats
DROP TABLE site_sensor_data_raw;
CREATE EXTERNAL TABLE site_sensor_data_raw (
    count int,
    dateTime8601 timestamp
)
PARTITIONED BY(year int, month int, day int, hour int)
ROW FORMAT  serde 'org.apache.hive.hcatalog.data.JsonSerDe'
with serdeproperties (
 'ignore.malformed.json' = 'true',
 "timestamp.formats"="yyyy-MM-dd'T'HH:mm:ss.SSS'Z',millis"
)
LOCATION 's3://bucket.me.com/raw/all-sites/';

ALTER TABLE site_sensor_data_raw ADD PARTITION (year='2017',month='03',day='09',hour='15') location 's3://bucket.me.com/raw/all-sites/2017/03/09/15';
ALTER TABLE site_sensor_data_raw ADD PARTITION (year='2017',month='03',day='09',hour='16') location 's3://bucket.me.com/raw/all-sites/2017/03/09/16';
ALTER TABLE site_sensor_data_raw ADD PARTITION (year='2017',month='03',day='09',hour='17') location 's3://bucket.me.com/raw/all-sites/2017/03/09/17';

DROP TABLE to_orc;
CREATE EXTERNAL TABLE to_orc (
      count int,
      dateTime8601 timestamp
)
STORED AS ORC
LOCATION 's3://bucket.me.com/orc'
TBLPROPERTIES ("orc.compress"="ZLIB");

INSERT OVERWRITE TABLE to_orc SELECT count,dateTime8601 FROM site_sensor_data_raw where year=2017 AND month=03 AND day=09 AND hour=15;

嗯,EMR和Athena上使用的默认JSON SerDe不能处理多行JSON记录。每个JSON记录应该在一行上

在多行JSON上,我从Hive/Hadoop甚至Presto(在Athen中使用)的角度看到了两个问题

  • 给定一个文件,显然Hive/Hadoop和JSON serde将无法识别JSON记录的结束和开始以返回其对象表示
  • 给定多个文件,多行JSON文件不像普通/n分隔的JSON文件那样可拆分
为了从EMR/Athena end解决这个问题,您需要根据您的数据结构编写自己的自定义SerDe,并捕获异常等

如何设置FireHose以忽略多行JSON

Firehose无法忽略特定格式。它将使用它的API(PutRecord或PutRecordBatch)将放入的任何内容作为数据blob,并将其发送到目的地

不管怎样,AWS Firehose通过AWS Lambda提供了数据转换,您可以使用Lambda函数转换Firehose上的数据传入数据,并将转换后的数据放入目标。因此,您可以使用该功能来识别和展平多行JSON。如果记录的格式不正确,您也可能会删除这些记录。您需要探索IOT如何将多行json数据发送到firehose(如逐行发送等),以编写您自己的函数

如果不可能,如何告诉配置单元在安装之前删除换行符 正在加载到表中或至少捕获异常并尝试继续

如果您的firehose目的地中仍然有多行JSON,因为您的ETL中有EMR,您可以使用它的compute而不是Lambda来展平JSON。spark上的此功能也可以帮助您实现这一点。


然后,您可以接收这些数据,创建一个列格式,供雅典娜处理

嗯,在EMR和Athena上使用的默认JSON SerDe不能用于多行JSON记录。每个JSON记录应该在一行上

在多行JSON上,我从Hive/Hadoop甚至Presto(在Athen中使用)的角度看到了两个问题

  • 给定一个文件,显然Hive/Hadoop和JSON serde将无法识别JSON记录的结束和开始以返回其对象表示
  • 给定多个文件,多行JSON文件不像普通/n分隔的JSON文件那样可拆分
为了从EMR/Athena end解决这个问题,您需要根据您的数据结构编写自己的自定义SerDe,并捕获异常等

如何设置FireHose以忽略多行JSON

Firehose无法忽略特定格式。它将使用它的API(PutRecord或PutRecordBatch)将放入的任何内容作为数据blob,并将其发送到目的地

不管怎样,AWS Firehose通过AWS Lambda提供了数据转换,您可以使用Lambda函数转换Firehose上的数据传入数据,并将转换后的数据放入目标。因此,您可以使用该功能来识别和展平多行JSON。如果记录的格式不正确,您也可能会删除这些记录。您需要探索IOT如何将多行json数据发送到firehose(如逐行发送等),以编写您自己的函数

如果不可能,如何告诉配置单元在安装之前删除换行符 正在加载到表中或至少捕获异常并尝试继续

如果您的firehose目的地中仍然有多行JSON,因为您的ETL中有EMR,您可以使用它的compute而不是Lambda来展平JSON。spark上的此功能也可以帮助您实现这一点。

然后,您可以接收这些数据,创建一个列格式,供雅典娜处理

--Example of converting to OEX/columnar formats
DROP TABLE site_sensor_data_raw;
CREATE EXTERNAL TABLE site_sensor_data_raw (
    count int,
    dateTime8601 timestamp
)
PARTITIONED BY(year int, month int, day int, hour int)
ROW FORMAT  serde 'org.apache.hive.hcatalog.data.JsonSerDe'
with serdeproperties (
 'ignore.malformed.json' = 'true',
 "timestamp.formats"="yyyy-MM-dd'T'HH:mm:ss.SSS'Z',millis"
)
LOCATION 's3://bucket.me.com/raw/all-sites/';

ALTER TABLE site_sensor_data_raw ADD PARTITION (year='2017',month='03',day='09',hour='15') location 's3://bucket.me.com/raw/all-sites/2017/03/09/15';
ALTER TABLE site_sensor_data_raw ADD PARTITION (year='2017',month='03',day='09',hour='16') location 's3://bucket.me.com/raw/all-sites/2017/03/09/16';
ALTER TABLE site_sensor_data_raw ADD PARTITION (year='2017',month='03',day='09',hour='17') location 's3://bucket.me.com/raw/all-sites/2017/03/09/17';

DROP TABLE to_orc;
CREATE EXTERNAL TABLE to_orc (
      count int,
      dateTime8601 timestamp
)
STORED AS ORC
LOCATION 's3://bucket.me.com/orc'
TBLPROPERTIES ("orc.compress"="ZLIB");

INSERT OVERWRITE TABLE to_orc SELECT count,dateTime8601 FROM site_sensor_data_raw where year=2017 AND month=03 AND day=09 AND hour=15;