AWS Glue Crawler 更新现有目录表的速度(非常)慢
AWS Glue Crawler updating existing catalog tables is (painfully) slow
我不断接收和存储 未压缩 JSON 对象的多个提要,分区 到一天,到不同的位置Amazon S3 存储桶(蜂巢式:s3://bucket/object=<object>/year=<year>/month=<month>/day=<day>/object_001.json
),并计划使用 AWS Glue 将此数据增量批处理并加载到 Parquet 数据湖:
- 爬虫将更新手动创建的 Glue tables,每个对象提要一个,用于架构和分区(新文件)更新;
- Glue ETL 作业 + 作业书签然后会不时地将每个对象提要的所有新分区批处理并映射到 Parquet 位置。
这种设计模式和架构似乎是一种非常安全的方法,因为它得到了许多 AWS 博客的支持,here and there。
我有一个这样配置的爬虫:
{
"Name": "my-json-crawler",
"Targets": {
"CatalogTargets": [
{
"DatabaseName": "my-json-db",
"Tables": [
"some-partitionned-json-in-s3-1",
"some-partitionned-json-in-s3-2",
...
]
}
]
},
"SchemaChangePolicy": {
"UpdateBehavior": "UPDATE_IN_DATABASE",
"DeleteBehavior": "LOG"
},
"Configuration": "{\"Version\":1.0,\"Grouping\":{\"TableGroupingPolicy\":\"CombineCompatibleSchemas\"}}"
}
并且每个 table 都被 "manually" 初始化为:
{
"Name": "some-partitionned-json-in-s3-1",
"DatabaseName": "my-json-db",
"StorageDescriptor": {
"Columns": [] # i'd like the crawler to figure this out on his first crawl,
"Location": "s3://bucket/object=some-partitionned-json-in-s3-1/",
"PartitionKeys": [
{
"Name": "year",
"Type": "string"
},
{
"Name": "month",
"Type": "string"
},
{
"Name": "day",
"Type": "string"
}
],
"TableType": "EXTERNAL_TABLE"
}
}
正如预期的那样,爬虫的第一个 运行 是一个小时左右的时间,但它成功地找出了 table 架构和现有分区。然而从那时起,重新运行爬虫所花的时间与第一次爬虫所花费的时间完全相同,甚至更长;这让我相信爬虫不仅在抓取新文件/分区,而且每次都会重新抓取所有整个 S3 位置。
请注意,两次抓取之间新文件的增量非常小(每次都很少有新文件)。
AWS Documentation 建议 运行 多个爬虫,但我不相信这会解决我的长期 运行 问题。我还考虑过在每次 运行 之后更新爬虫排除模式,但与通过 Lambda boto3 魔法手动更新表分区相比,我发现使用爬虫的优势太少了。
我是不是遗漏了什么?关于爬虫更新现有数据目录而不是直接爬取数据存储,我可能会误解一个选项?
有什么改进我的数据编目的建议吗?考虑到在 Glue tables 中索引这些 JSON 文件对我来说只是必要的,因为我希望我的 Glue 作业使用书签。
谢谢!
我的这个悬而未决的问题仍然得到了一些点击,所以我想分享一个我当时认为足够的解决方案:我最终根本没有使用爬虫逐步更新我的 Glue tables.
使用 S3 事件 / S3 Api 通过 CloudTrail / S3 Eventbridge 通知调用(选择一个),最终编写了一个 lambda,它在 Athena 上弹出一个 ALTER TABLE ADD PARTITION
DDL 查询,更新一个已经存在的 Glue table 使用新创建的分区,基于 S3 密钥前缀。在我看来,这是维护 Glue table 的一种很好的 straight-forward 和 low-code 方法;唯一的缺点是处理服务节流(Lambda 和 Athena),以及查询失败以避免在此过程中丢失任何数据。
这个解决方案扩展得很好,因为每个帐户的并行 DDL 查询是一个 soft-limit 配额,可以随着更新越来越多 table 的需求增加而增加;对于 non-time-critical 工作流程来说效果很好。
如果您限制 S3 写入 Glue tables S3 分区(在此特定实现中,每个 Glue table 分区一个文件是理想的),使用 Kinesis 对数据进行批处理,效果会更好例如 DeliveryStream。
我不断接收和存储 未压缩 JSON 对象的多个提要,分区 到一天,到不同的位置Amazon S3 存储桶(蜂巢式:s3://bucket/object=<object>/year=<year>/month=<month>/day=<day>/object_001.json
),并计划使用 AWS Glue 将此数据增量批处理并加载到 Parquet 数据湖:
- 爬虫将更新手动创建的 Glue tables,每个对象提要一个,用于架构和分区(新文件)更新;
- Glue ETL 作业 + 作业书签然后会不时地将每个对象提要的所有新分区批处理并映射到 Parquet 位置。
这种设计模式和架构似乎是一种非常安全的方法,因为它得到了许多 AWS 博客的支持,here and there。
我有一个这样配置的爬虫:
{
"Name": "my-json-crawler",
"Targets": {
"CatalogTargets": [
{
"DatabaseName": "my-json-db",
"Tables": [
"some-partitionned-json-in-s3-1",
"some-partitionned-json-in-s3-2",
...
]
}
]
},
"SchemaChangePolicy": {
"UpdateBehavior": "UPDATE_IN_DATABASE",
"DeleteBehavior": "LOG"
},
"Configuration": "{\"Version\":1.0,\"Grouping\":{\"TableGroupingPolicy\":\"CombineCompatibleSchemas\"}}"
}
并且每个 table 都被 "manually" 初始化为:
{
"Name": "some-partitionned-json-in-s3-1",
"DatabaseName": "my-json-db",
"StorageDescriptor": {
"Columns": [] # i'd like the crawler to figure this out on his first crawl,
"Location": "s3://bucket/object=some-partitionned-json-in-s3-1/",
"PartitionKeys": [
{
"Name": "year",
"Type": "string"
},
{
"Name": "month",
"Type": "string"
},
{
"Name": "day",
"Type": "string"
}
],
"TableType": "EXTERNAL_TABLE"
}
}
正如预期的那样,爬虫的第一个 运行 是一个小时左右的时间,但它成功地找出了 table 架构和现有分区。然而从那时起,重新运行爬虫所花的时间与第一次爬虫所花费的时间完全相同,甚至更长;这让我相信爬虫不仅在抓取新文件/分区,而且每次都会重新抓取所有整个 S3 位置。
请注意,两次抓取之间新文件的增量非常小(每次都很少有新文件)。
AWS Documentation 建议 运行 多个爬虫,但我不相信这会解决我的长期 运行 问题。我还考虑过在每次 运行 之后更新爬虫排除模式,但与通过 Lambda boto3 魔法手动更新表分区相比,我发现使用爬虫的优势太少了。
我是不是遗漏了什么?关于爬虫更新现有数据目录而不是直接爬取数据存储,我可能会误解一个选项?
有什么改进我的数据编目的建议吗?考虑到在 Glue tables 中索引这些 JSON 文件对我来说只是必要的,因为我希望我的 Glue 作业使用书签。
谢谢!
我的这个悬而未决的问题仍然得到了一些点击,所以我想分享一个我当时认为足够的解决方案:我最终根本没有使用爬虫逐步更新我的 Glue tables.
使用 S3 事件 / S3 Api 通过 CloudTrail / S3 Eventbridge 通知调用(选择一个),最终编写了一个 lambda,它在 Athena 上弹出一个 ALTER TABLE ADD PARTITION
DDL 查询,更新一个已经存在的 Glue table 使用新创建的分区,基于 S3 密钥前缀。在我看来,这是维护 Glue table 的一种很好的 straight-forward 和 low-code 方法;唯一的缺点是处理服务节流(Lambda 和 Athena),以及查询失败以避免在此过程中丢失任何数据。
这个解决方案扩展得很好,因为每个帐户的并行 DDL 查询是一个 soft-limit 配额,可以随着更新越来越多 table 的需求增加而增加;对于 non-time-critical 工作流程来说效果很好。
如果您限制 S3 写入 Glue tables S3 分区(在此特定实现中,每个 Glue table 分区一个文件是理想的),使用 Kinesis 对数据进行批处理,效果会更好例如 DeliveryStream。