it-roy-ru.com

Каков рекомендуемый способ удаления большого количества элементов из DynamoDB?

Я пишу простой сервис регистрации в DynamoDB.

У меня есть таблица журналов, которая основана на хэше user_id и диапазоне меток времени (Unix Epoch int).

Когда пользователь службы закрывает свою учетную запись, мне нужно удалить все элементы в таблице, независимо от значения диапазона.

Каков рекомендуемый способ выполнения такой операции (имея в виду, что можно удалить миллионы элементов)?

Мои варианты, насколько я вижу:

A: Выполните операцию сканирования, вызывая удаление для каждого возвращенного элемента, пока не останется ни одного элемента

B: Выполните операцию BatchGet, снова вызывая удаление для каждого элемента, пока не останется ни одного

Оба они выглядят ужасно для меня, так как они займут много времени.

В идеале я хочу вызвать LogTable.DeleteItem (user_id) - без указания диапазона и удалить все для меня.

70
Tyler

В идеале я хочу вызвать LogTable.DeleteItem (user_id) - Не предоставляя диапазон, и имейте это, удаляют все для меня.

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

  1. Используйте Query вместо Scan , чтобы получить все элементы для user_id - это работает независимо от используемого объединенного первичного ключа хеша/диапазона, потому что HashKeyValue и RangeKeyCondition это отдельные параметры в этом API, и первый предназначен только для значение атрибута хеш-компонента составного первичного ключа..

    • Обратите внимание, что здесь вам, как обычно, придется разбираться с страницей API запросов, см. Параметр ExclusiveStartKey:

      Первичный ключ элемента, с которого можно продолжить предыдущий запрос. более ранний запрос может предоставить это значение как LastEvaluatedKey, если это операция запроса была прервана до завершения запроса; или из-за размера набора результатов или параметра Limit. LastEvaluatedKey можно передать обратно в новом запросе, чтобы продолжить операция с этого момента.

  2. Цикл по всем возвращенным элементам и либо облегчить DeleteItem как обычно

    • Update: Скорее всего BatchWriteItem больше подходит для такого случая использования (подробности см. Ниже).

Обновление

Как было отмечено ivant , BatchWriteItem operation позволяет поместить или удалить несколько элементов в нескольких таблицах за один вызов API [выделение мин]:

Чтобы загрузить один элемент, вы можете использовать API PutItem и удалить один пункт, вы можете использовать API DeleteItem. Однако, когда вы хотите загрузить или удалите большие объемы данных, например загрузите большие объемы данные из Amazon Elastic MapReduce (EMR) или перенести данные из другого База данных в Amazon DynamoDB, этот API предлагает эффективную альтернатива.

Обратите внимание, что это все еще имеет некоторые соответствующие ограничения, в частности:

  • Максимум операций в одном запросе - Вы можете указать до 25 операций ввода или удаления; однако общий размер запроса не может превышать 1 МБ (полезная нагрузка HTTP).

  • Не атомарная операция - отдельные операции, указанные в BatchWriteItem, являются атомарными; однако BatchWriteItem в целом является операцией «наилучшего усилия», а не атомарной операцией. То есть в запросе BatchWriteItem некоторые операции могут завершиться успешно, а другие могут завершиться с ошибкой. [...]

Тем не менее, это, очевидно, предлагает потенциально значительный выигрыш для вариантов использования, подобных тому, который имеется в наличии.

42
Steffen Opel

Согласно документации DynamoDB вы можете просто удалить всю таблицу.

Увидеть ниже:

«Удаление всей таблицы значительно эффективнее, чем удаление элементов по одному, что существенно удваивает пропускную способность записи, так как вы выполняете столько операций удаления, сколько операций put»

Если вы хотите удалить только подмножество ваших данных, то вы можете составить отдельные таблицы для каждого месяца, года или аналогичного. Таким образом, вы можете удалить «последний месяц» и сохранить остальные данные в целости и сохранности.

Вот как вы удаляете таблицу в Java с помощью AWS SDK:

DeleteTableRequest deleteTableRequest = new DeleteTableRequest()
  .withTableName(tableName);
DeleteTableResult result = client.deleteTable(deleteTableRequest);
40
jonathan

Если вы хотите удалить элементы через некоторое время, например, через месяц просто используйте опцию Time To Live. Не будет считать количество записываемых единиц.

В вашем случае я бы добавил ttl, когда истекает срок действия логов, и оставляю их после удаления пользователя. TTL в конце концов убедится, что журналы удалены.

Когда Time To Live включен для таблицы, фоновое задание проверяет TTL атрибут элементов, чтобы увидеть, если они истекли.

DynamoDB обычно удаляет просроченные элементы в течение 48 часов после истечения срока действия. Точная продолжительность, в течение которой элемент действительно удаляется после истечения срока действия зависит от характера рабочей нагрузки и размер стола. Элементы, срок действия которых истек и которые не были удалены, будут по-прежнему отображаются в чтениях, запросах и сканированиях. Эти предметы все еще могут быть обновленные и успешные обновления для изменения или удаления срока действия Атрибут будет соблюдаться.

https://docs.aws.Amazon.com/amazondynamodb/latest/developerguide/TTL.htmlhttps://docs.aws.Amazon.com/amazondynamodb/latest/developerguide/howitworks- ttl.html

6
Lukas

Ответ на этот вопрос зависит от количества предметов, их размера и вашего бюджета. От этого зависит 3 случая:

1- Количество предметов и размер предметов в таблице не очень много. затем, как сказал Штеффен Опель, вы можете использовать Query вместо Scan, чтобы получить все элементы для user_id, а затем перебрать все возвращенные элементы и либо облегчить DeleteItem или BatchWriteItem. Но имейте в виду, что вы можете сжечь много пропускной способности здесь. Например, рассмотрим ситуацию, когда вам нужно удалить 1000 элементов из таблицы DynamoDB. Предположим, что каждый элемент имеет размер 1 КБ, в результате чего получается около 1 МБ данных. Эта задача массового удаления потребует в общей сложности 2000 единиц емкости записи для запроса и удаления. Чтобы выполнить эту загрузку данных в течение 10 секунд (что даже не считается быстрым в некоторых приложениях), вам необходимо установить для пропускной способности записи таблицы 200 единиц емкости записи. Как вы можете видеть, это можно использовать таким образом, если его для меньшего количества предметов или предметов небольшого размера.

2- У нас в таблице много предметов или очень больших предметов, и мы можем хранить их в зависимости от времени в разных таблицах. Тогда как Джонатан сказал, что вы можете просто удалить таблицу. это намного лучше, но я не думаю, что это соответствует вашему делу. Поскольку вы хотите удалить данные всех пользователей независимо от времени создания журналов, в этом случае вы не можете удалить конкретную таблицу. если вы хотите иметь отдельную таблицу для каждого пользователя, то я думаю, что если количество пользователей велико, то это так дорого, и это не практично для вашего случая.

3- Если у вас много данных, и вы не можете разделить ваши горячие и холодные данные на разные таблицы, и вам необходимо часто выполнять крупномасштабное удаление, то, к сожалению, DynamoDB вам совсем не подходит. Это может стать дороже или очень медленно (зависит от вашего бюджета). В этих случаях я рекомендую найти другую базу данных для ваших данных.

2
Iman Sedighi

У нас нет возможности обрезать динамо-таблицы. мы должны отбросить таблицу и создать заново. DynamoDB Charges основан на ReadCapacityUnits и WriteCapacityUnits. Если мы удалим все элементы, используя функцию BatchWriteItem, она будет использовать WriteCapacityUnits. Так что лучше удалить определенные записи или удалить таблицу и начать заново.

0
Shraavan Hebbar

Мой подход к удалению всех строк из таблицы в DynamoDb состоит в том, чтобы просто извлечь все строки из таблицы, используя DynamoDbs ScanAsync, а затем передать список результатов в DynamoDbs AddDeleteItems. Ниже код в C # работает нормально для меня.

        public async Task DeleteAllReadModelEntitiesInTable()
    {
        List<ReadModelEntity> readModels;

        var conditions = new List<ScanCondition>();
        readModels = await _context.ScanAsync<ReadModelEntity>(conditions).GetRemainingAsync();

        var batchWork = _context.CreateBatchWrite<ReadModelEntity>();
        batchWork.AddDeleteItems(readModels);
        await batchWork.ExecuteAsync();
    }

Примечание. Удаление таблицы и ее повторное создание из веб-консоли может вызвать проблемы при использовании таблицы YAML/CloudFront. 

0
Mohammad