簡體   English   中英

具有分頁功能的DynamoDB Python查詢(不掃描)

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM