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

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

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

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

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

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

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

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

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

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

Ответы [ 6 ]

44 голосов
/ 06 февраля 2012

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

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

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

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

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

  2. Зацикливание на всех возвращенных товарах и либо облегчение DeleteItem как обычно

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

Обновление

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

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

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

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

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

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

43 голосов
/ 15 апреля 2013

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

См. Ниже:

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

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

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

DeleteTableRequest deleteTableRequest = new DeleteTableRequest()
  .withTableName(tableName);
DeleteTableResult result = client.deleteTable(deleteTableRequest);
8 голосов
/ 13 июня 2018

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

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

Когда для таблицы включено Time To Live, фоновое задание проверяет атрибут TTL элементов, чтобы определить, не истек ли срок их действия.DynamoDB обычно удаляет просроченные элементы в течение 48 часов после истечения срока действия.Точная продолжительность, в течение которой элемент действительно удаляется после истечения срока действия, зависит от характера рабочей нагрузки и размера таблицы.Элементы, срок действия которых истек и которые не были удалены, все равно будут отображаться при чтении, запросах и сканировании.Эти элементы все еще могут быть обновлены, и успешные обновления для изменения или удаления атрибута срока действия будут учитываться.

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

2 голосов
/ 26 мая 2016

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

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

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

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

0 голосов
/ 23 января 2019

Мой подход к удалению всех строк из таблицы в 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 голосов
/ 06 июня 2018

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

...