You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Boto3 S3 Resource的objects.filter查询远慢于Client?

S3桶批量获取对象列表:Boto3 Resource与Client的性能差异问题

我需要从一个包含数十亿对象的S3桶中获取对象列表,该桶下有数百个文件夹,每个文件夹内有数百万级对象。目前遇到的核心问题是:使用boto3 S3 Resource的bucket.objects.filter方法时速度极慢,能否在保留Resource便捷性的同时,达到与Client相同的性能?

测试结果

以下是不同实现方式的耗时对比:

s3 = boto3.resource("s3")
s3bucket = s3.Bucket("myBucket")
# folder1/下有数千万级对象,folder1/hello09_前缀下有数百万级对象(示例:s3://myBucket/folder1/hello09_file0000001)
s3objects = s3bucket.objects.filter(Prefix="folder1/hello09_") # 尝试设置page_size(1000)无明显变化
  • 列表推导式遍历:耗时约21分钟
    tmp = [s3obj.key for s3obj in s3objects] 
    
  • 普通循环遍历:耗时约20分钟
    tmp = []
    for s3obj in s3objects:
        tmp.append(s3obj.key)
    
  • S3 Client批量循环(指定完整前缀):耗时约2分钟
    client = boto3.client('s3')
    # 使用NextContinuationToken循环,每次获取1000个对象
    response = client.list_objects_v2(Bucket="myBucket", Prefix="folder1/hello09_")
    # 后续循环处理NextContinuationToken逻辑省略
    
  • S3 Client批量循环(仅指定文件夹前缀):耗时约31分钟
    client = boto3.client('s3')
    # 使用NextContinuationToken循环,每次获取1000个对象
    response = client.list_objects_v2(Bucket="myBucket", Prefix="folder1/")
    # 后续循环处理NextContinuationToken逻辑省略
    
    额外的10分钟耗时可能源于需要在本地过滤出符合hello09_前缀的对象,并逐个追加到数组中

最初猜测

我最初以为bucket.objects.filter会先查询folder1/下的所有对象,再在本地过滤出符合hello09_前缀的结果,而非像Client那样直接向S3发起带完整前缀的查询请求。也曾怀疑Resource是逐个查询对象而非批量获取1000条,但在少量对象的测试场景中,resource.bucket.objects.filter与client.list_objects_v2的性能表现一致。

这是否是Boto3过滤逻辑的bug?有没有办法规避这个性能问题,让Resource达到Client的效率?

更新1:请求路径验证与后台开销分析

通过详细日志验证,Resource实际发送了正确的带完整前缀的过滤请求。日志中虽存在少量错误重试、区域重定向、DNS检查等操作,但这些不足以导致额外18分钟的耗时。推测问题出在Resource的后台数据处理开销上——相比Client,Resource可能在返回结果后做了更多额外的对象实例化或数据处理工作。

目前无法使用S3 Inventory Report(存在非实时等问题),那是否只能放弃Resource改用Client?难道S3 Resource仅在处理少量对象时性能与Client一致,处理大量对象时天生存在内部效率问题?我希望通过参数调整让Resource达到相同性能,但如果是底层实现的问题,可能无法实现——毕竟Resource无需手动管理continuationTokens,使用起来更便捷。

相关请求日志:

botocore.endpoint [DEBUG] Sending http request: <AWSPreparedRequest stream_output=False, method=GET, 
url=https://myBucket.s3.xxxx.amazonaws.com/?prefix=myFolder1%2Fhello09_&encoding-type=url, 
headers={'User-Agent': b'Boto3/1.20.24 Python/3.8.0 Windows Botocore/1.27.59 Resource', 'X-Amz-Date': b'xxx', 
'X-Amz-Content-SHA256': b'xxx', 'Authorization': b'xxx', 'amz-sdk-invocation-id': b'xxx', 'amz-sdk-request': b'attempt=1'}>
...
botocore.parsers [DEBUG] Response headers: ...
...
[DEBUG] Event needs-retry.s3.ListObjects: calling handler <botocore.retryhandler.RetryHandler object at 0x000000????>
botocore.retryhandler [DEBUG] No retry needed.

更新2:API版本与请求参数差异分析

对比Resource与Client的HTTP请求,发现关键差异:

  • Client使用的是S3 ListObjects V2 API(URL中包含list-type=2),并通过continuation-token实现续传
  • Resource使用的是旧版ListObjects V1 API,通过marker参数实现续传

这可能是性能差异的核心原因:ListObjects V1在处理大量对象时,S3服务端计算续传位置的效率低于V2;此外,Resource会为每个返回的对象创建对应的Python对象实例,数百万级的对象实例化操作会带来额外的开销,进一步拖慢整体速度。

请求URL对比:

Client请求URL

url=https://myBucket.s3.xxx.amazonaws.com/
?list-type=2&
prefix=myFolder1%2Fhello_&
continuation-token=xxx
encoding-type=url, 

Resource请求URL

url=https://myBucket.s3.xxx.amazonaws.com/
?
prefix=myFolder1%2Fhello_&
marker=myFolder1%2Fhello_world001&
encoding-type=url, 

内容的提问来源于stack exchange,提问作者Ranald Fong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 22:30:29