Клиент DynamoDB.Scan() не возвращает параметр LastEvaluatedKey

#amazon-web-services #amazon-dynamodb

#amazon-web-services #amazon-dynamodb

Вопрос:

У меня есть таблица с 10 тыс. строк. Я пытаюсь проанализировать их, чтобы изменить небольшую вещь внутри атрибута (внутри каждой строки) с помощью Python, поэтому я использую client.scan(), берущий пакеты по 10 строк и присваивающий параметр «LastEvaluatedKey» следующему .scan().

Проблема в том, что после 40 строк scan() не возвращает lastKey, как и DB, длиной всего 40 строк.

Я заметил, что при запуске того же скрипта для другой таблицы, в 3 раза больше, остановка происходит в 120 строках (в 3 раза больше).

Таблица имеет емкость по требованию.

Есть идеи по этому поводу?

 client = boto3.client('dynamodb')
resource = boto3.resource('dynamodb')
table = resource.Table(table_name)

remaining = 3961
iteration = 0
limit = 10

while remaining > 0:
    # retrieve Limit
    if iteration == 0:
        response = client.scan(
            TableName=table_name,
            Limit=limit,
            Select='ALL_ATTRIBUTES',
            ReturnConsumedCapacity='TOTAL',
            TotalSegments=123,
            Segment=122,
        )
        key = response["LastEvaluatedKey"]
    else:

        response = client.scan(
            TableName=table_name,
            Limit=limit,
            Select='ALL_ATTRIBUTES',
            ExclusiveStartKey=key,
            ReturnConsumedCapacity='TOTAL',
            TotalSegments=123,
            Segment=122,
        )

        key = response["LastEvaluatedKey"]

    iteration  = 1
    for el in response["Items"]:
        print(el) 
  

Ответ №1:

Я думаю, что есть две проблемы:

  1. похоже, вы сканируете с ограничением: попробуйте удалить это

  2. вы выполняете параллельное сканирование и всегда просматриваете последний сегмент:

    Итоговые сегменты = 123 Сегмент = 122

Я не уверен, насколько велики ваши таблицы, но 123 сегмента — это довольно много, и я не вижу, чтобы вы сканировали какие-либо другие сегменты, от 0 до 121.


Попробуйте это:

 iteration = 0
response = client.scan(
    TableName=table_name,
    Select='ALL_ATTRIBUTES',
    ReturnConsumedCapacity='TOTAL'
)
while True:
    iteration  = 1
    for el in response["Items"]:
        print(el)
    last_key = response["LastEvaluatedKey"]
    if not last_key: 
        break
    response = client.scan(
        TableName=table_name,
        Select='ALL_ATTRIBUTES',
        ExclusiveStartKey=last_key,
        ReturnConsumedCapacity='TOTAL'           
    )
  

Я ожидаю, что вышеуказанное должно сработать для извлечения всех элементов в вашей таблице. Затем, если вы все еще хотите запустить параллельное сканирование, вы можете это сделать, но вам придется обрабатывать разделение на сегменты, и для того, чтобы это было эффективно, вам придется обрабатывать их одновременный запуск (что сложнее сделать, чем последовательное сканирование).

Комментарии:

1. Большое тебе спасибо, Майк, проблема заключалась, по сути, в сегменте.

2. Отлично! Если это отвечает на ваш вопрос, подумайте о принятии ответа