我做了以下的事情,以便在我的水桶中找到模式
def getListOfPrefixesFromS3(dataPath: String, prefix: String, delimiter: String, batchSize: Integer): List[String] = {
var s3Client = new AmazonS3Client()
var listObjectsRequest = new ListObjectsRequest().withBucketName(dataPath).withMaxKeys(batchSize).withPrefix(prefix).withDelimiter(delimiter)
var objectListing: ObjectListing = null
var res: List[String] = List()
do {
objectListing = s3Client.listObjects(listObjectsRequest)
res = res ++ objectListing.getCommonPrefixes
listObjectsRequest.setMarker(objectListing.getNextMarker)
} while (objectListing.isTruncated)
res
}
对于较大的存储桶,由于所有对象摘要都是由Aws返回的,而不仅仅是与前缀和分隔符匹配的对象摘要,因此会消耗太多时间。我正在寻找提高性能的方法,到目前为止我只发现我应该为密钥命名并将它们妥善组织在桶中。
如果有人能指出我正确的方向,或者给我一个提示,那将是非常有用的,无论它多么小可能会非常好。
我正在使用java sdk for AWS,这段代码在一个spark作业中运行,主要是在scala中。
编辑1:因为我正在使用火花。我开始做的是找到带有分隔符的键作为" /"。这给了我很多常见的前缀或说顶级文件夹。然后我用,
sc.parallelize(keys).map(key => getListOfPrefixesForKey(key))
获取所有密钥的列表。我希望通过充分的并行化,这将加速为我搜索密钥。由于我无法移动数据或对其进行重组,我认为这是我的唯一途径。
任何人都可以添加如何更有效地使用spark找到密钥?
答案 0 :(得分:1)
S3不提供随机访问密钥查找功能 - 除非您的对象密钥具有语义含义且可以通过前缀定位,否则没有内置功能允许索引搜索。
许多AWS服务专注于其核心竞争力,并且不提供与不同AWS服务可用功能重叠的功能。这是一个例子。
一个常见的解决方案是构建一个将可查询属性映射到S3对象键的外部索引。
这是official AWS Blog Post引用该主题的引用。
此索引可以利用为快速查找而构建的数据存储库,但可能不太适合存储大型数据blob。
举例来说:在我的环境中,我用于此目的的解决方案之一是RDS上的MariaDB,它维护受监视桶中所有密钥的索引 - 以及所有对象版本,用于版本化桶 - 以及所有对象属性(大小,日期,etag)和元数据,它们也是索引和可搜索的。数据库由S3事件自动更新,这些事件将进入SQS队列,并在那里进行处理。
但我并不是说这是The One True Way™。
没有一种正确的方法 - 有许多技术非常适合这种应用。 S3事件通知功能允许自动近乎实时地维护索引,维护索引的代码可以在EC2中运行,也可以使用Lambda运行无服务器。
上面链接的博文解释了如何使用DynamoDB执行此操作。