DynamoDB Client.Scan()未返回LastEvaluatedKey问题咨询
问题原因分析及解决方案
哦,我一眼就看穿问题所在了——你在使用分段扫描(Segmented Scan),但代码只处理了单个Segment的数据,自然扫完这个Segment就停了!
核心原因拆解
你代码里设置了TotalSegments=123和Segment=122:
TotalSegments表示把整个表的数据拆分成123个独立的、不重叠的分片;Segment参数指定你只扫描第123个分片(因为Segment的索引从0开始,122是最后一个分片)。
DynamoDB的分段扫描中,每个分片的数据量是不均匀的:你测试的第一张表的第122分片刚好只有40条数据,另一张3倍规模的表对应分片有120条。当你扫完这个分片的所有数据后,DynamoDB就不会再返回LastEvaluatedKey了——因为这个分片已经没有更多数据可扫,而你的代码完全没去处理剩下的122个分片。
按需容量模式和这个问题无关,锅全在分段扫描的参数使用上。
解决方案
根据你的需求,有两种修正方式:
1. 不需要并行扫描:移除分段参数
如果你只是想遍历整个表的所有数据,不需要并行加速,直接删掉TotalSegments和Segment这两个参数即可,这样scan会遍历全表直到没有更多数据:
import boto3 client = boto3.client('dynamodb') table_name = "你的表名" limit = 10 last_evaluated_key = None while True: scan_params = { 'TableName': table_name, 'Limit': limit, 'Select': 'ALL_ATTRIBUTES', 'ReturnConsumedCapacity': 'TOTAL' } if last_evaluated_key: scan_params['ExclusiveStartKey'] = last_evaluated_key response = client.scan(**scan_params) # 处理当前页的数据 for item in response["Items"]: print(item) # 检查是否还有下一页 last_evaluated_key = response.get("LastEvaluatedKey") if not last_evaluated_key: break
2. 需要并行扫描:遍历所有Segment
如果你的表数据量极大,想用并行扫描提升效率,那你需要遍历所有Segment(从0到122),每个Segment单独执行扫描循环。可以用线程池来实现并行处理:
import boto3 from concurrent.futures import ThreadPoolExecutor client = boto3.client('dynamodb') table_name = "你的表名" limit = 10 total_segments = 123 def process_segment(segment_id): last_key = None while True: scan_params = { 'TableName': table_name, 'Limit': limit, 'Select': 'ALL_ATTRIBUTES', 'ReturnConsumedCapacity': 'TOTAL', 'TotalSegments': total_segments, 'Segment': segment_id } if last_key: scan_params['ExclusiveStartKey'] = last_key response = client.scan(**scan_params) # 处理当前Segment的分页数据 for item in response["Items"]: print(item) last_key = response.get("LastEvaluatedKey") if not last_key: break # 启动线程池并行处理所有Segment with ThreadPoolExecutor(max_workers=10) as executor: executor.map(process_segment, range(total_segments))
内容的提问来源于stack exchange,提问作者Giacomo Ciarlini
相关产品推荐
相关产品推荐

