[英]DynamoDB Python Query with Pagination (not scan)
我正在使用以下代碼通過DynamoDB查詢進行查詢和分頁:
class DecimalEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, decimal.Decimal):
return str(o)
return super(DecimalEncoder, self).default(o)
def run(date: int, start_epoch: int, end_epoch: int):
dynamodb = boto3.resource('dynamodb',
region_name='REGION',
config=Config(proxies={'https': 'PROXYIP'}))
table = dynamodb.Table('XYZ')
response = table.query(
# ProjectionExpression="#yr, title, info.genres, info.actors[0]", #THIS IS A SELECT STATEMENT
# ExpressionAttributeNames={"#yr": "year"}, #SELECT STATEMENT RENAME
KeyConditionExpression=Key('date').eq(date) & Key('uid').between(start_epoch, end_epoch)
)
for i in response[u'Items']:
print(json.dumps(i, cls=DecimalEncoder))
while 'LastEvaluatedKey' in response:
response = table.scan( ##IS THIS INEFFICIENT CODE?
# ProjectionExpression=pe,
# FilterExpression=fe,
# ExpressionAttributeNames=ean,
ExclusiveStartKey=response['LastEvaluatedKey']
)
for i in response['Items']:
print(json.dumps(i, cls=DecimalEncoder))
盡管此代碼有效,但它的運行速度極其慢,我擔心' response = table.scan
'是此結果。 我的印象是查詢比掃描要快得多(因為掃描需要表的整個迭代)。 此代碼是否導致數據庫表的完整迭代?
這可能是一個單獨的問題,但是這樣做有更有效的方法(帶有代碼示例)嗎? 我嘗試使用Boto3的分頁功能,但也無法在查詢中使用它。
不幸的是,是的,“掃描”操作會讀取整個表。 您沒有說表的分區鍵是什么,但是如果它是一個日期,那么您在這里真正要做的就是讀取一個分區,而這實際上是“查詢”操作更有效的方法,因為它可以直接跳轉到所需的分區,而不用掃描整個表來查找它。
即使使用Query,您仍然仍然需要像您一樣進行分頁,因為分區中仍有很多項目的可能性。 但是至少您不會掃描整個表。
順便說一句,掃描整個表將花費很多讀取操作。 您可以問一下AWS為您分配了多少次讀取,這可以幫助您發現讀取過多的情況-除了您注意到的明顯緩慢之外。
Nadav Har'El提供的答案是解決此問題的關鍵。 我通過執行初始DynamoDB查詢來錯誤地使用DynamoDB分頁代碼示例,但是隨后使用scan進行分頁!
正確的方法是最初使用查詢AND進行分頁:
class DecimalEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, decimal.Decimal):
return str(o)
return super(DecimalEncoder, self).default(o)
def run(date: int, start_epoch: int, end_epoch: int):
dynamodb = boto3.resource('dynamodb',
region_name='REGION',
config=Config(proxies={'https': 'PROXYIP'}))
table = dynamodb.Table('XYZ')
response = table.query(
KeyConditionExpression=Key('date').eq(date) & Key('uid').between(start_epoch, end_epoch)
)
for i in response[u'Items']:
print(json.dumps(i, cls=DecimalEncoder))
while 'LastEvaluatedKey' in response:
response = table.query(
KeyConditionExpression=Key('date').eq(date) & Key('uid').between(start_epoch, end_epoch),
ExclusiveStartKey=response['LastEvaluatedKey']
)
for i in response['Items']:
print(json.dumps(i, cls=DecimalEncoder))
我仍然將Nadav Har'El的回答標記為正確,因為正是他的回答導致了此代碼示例。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.