AWS Athena 如何处理单行 JSON?
How AWS Athena deals with single line JSONs?
我目前正在使用 Athena 以及 Kinesis Firehose
、Glue Crawler
。 Kinesis Firehose
正在将 JSON 保存到单行文件,如下所示
{"name": "Jone Doe"}{"name": "Jane Doe"}{"name": "Jack Doe"}
但是我注意到athena查询的是select count(*) from db.names
returns1而不是3。经过搜索发现问题所在。我找到了以下文档。
文章说 JSON files 文件应该用新行存储。
{"name": "Jone Doe"}
{"name": "Jane Doe"}
{"name": "Jack Doe"}
在单行 JSON 文件上 运行 athena 查询是否有一些巧妙的技巧?
更新
感谢@Constantine,AWS Athena 正在执行分布式处理。由于单行 JSON 文件没有分隔符,因此无法进行分布式处理。因此,您必须在保存文件之前对其进行转换。
Kinesis Firehose 提供使用 Lambda 的转换,我添加了以下转换,以便从 AWS Athena 查询数据。
const addNewLine = (data) => {
const parsedData = JSON.parse(new Buffer.from(data,'base64').toString('utf8'));
return new Buffer.from(JSON.stringify(parsedData) + '\n').toString('base64')
}
exports.handler = async (event, context) => {
const output = event.records.map((record) => ({
recordId: record.recordId,
result: 'Ok',
data: addNewLine(record.data),
}));
return { records: output };
};
我通过以下 link 想出了这段代码
我认为无法正确处理具有此类 JSON 的文件,因为需要分隔符才能分配工作。文档中没有关于如何提供自定义分隔符的明确信息,很可能在受支持的 JSON SerDe 库中是不可能的。除此之外,给定的 JSON 对象之间没有明显的分隔符,这些分隔符没有在 JSON 本身内部使用。事实上,根本就没有分隔符。
但是,可以使用 Firehose 数据转换来缓冲传入数据并异步调用每个缓冲区的 Lambda 函数。有预定义的 Lambda 蓝图,在这种情况下可以使用 Kinesis Firehose Processing
在 JSON 个对象之间添加换行符。
每个转换后的记录都应该包含 recordId
、result
和 Base64 编码 data
以及转换后的负载。
这种 Lambda 函数有多个示例,例如this python sample 在 GitHub 上的亚马逊 AWS 示例回购中。
我目前正在使用 Athena 以及 Kinesis Firehose
、Glue Crawler
。 Kinesis Firehose
正在将 JSON 保存到单行文件,如下所示
{"name": "Jone Doe"}{"name": "Jane Doe"}{"name": "Jack Doe"}
但是我注意到athena查询的是select count(*) from db.names
returns1而不是3。经过搜索发现问题所在。我找到了以下文档。
文章说 JSON files 文件应该用新行存储。
{"name": "Jone Doe"}
{"name": "Jane Doe"}
{"name": "Jack Doe"}
在单行 JSON 文件上 运行 athena 查询是否有一些巧妙的技巧?
更新
感谢@Constantine,AWS Athena 正在执行分布式处理。由于单行 JSON 文件没有分隔符,因此无法进行分布式处理。因此,您必须在保存文件之前对其进行转换。
Kinesis Firehose 提供使用 Lambda 的转换,我添加了以下转换,以便从 AWS Athena 查询数据。
const addNewLine = (data) => {
const parsedData = JSON.parse(new Buffer.from(data,'base64').toString('utf8'));
return new Buffer.from(JSON.stringify(parsedData) + '\n').toString('base64')
}
exports.handler = async (event, context) => {
const output = event.records.map((record) => ({
recordId: record.recordId,
result: 'Ok',
data: addNewLine(record.data),
}));
return { records: output };
};
我通过以下 link 想出了这段代码
我认为无法正确处理具有此类 JSON 的文件,因为需要分隔符才能分配工作。文档中没有关于如何提供自定义分隔符的明确信息,很可能在受支持的 JSON SerDe 库中是不可能的。除此之外,给定的 JSON 对象之间没有明显的分隔符,这些分隔符没有在 JSON 本身内部使用。事实上,根本就没有分隔符。
但是,可以使用 Firehose 数据转换来缓冲传入数据并异步调用每个缓冲区的 Lambda 函数。有预定义的 Lambda 蓝图,在这种情况下可以使用 Kinesis Firehose Processing
在 JSON 个对象之间添加换行符。
每个转换后的记录都应该包含 recordId
、result
和 Base64 编码 data
以及转换后的负载。
这种 Lambda 函数有多个示例,例如this python sample 在 GitHub 上的亚马逊 AWS 示例回购中。