Cách được đề xuất để xóa một số lượng lớn các mục khỏi DynamoDB là gì?


111

Tôi đang viết một dịch vụ ghi nhật ký đơn giản trong DynamoDB.

Tôi có một bảng nhật ký được khóa bởi hàm băm user_id và một phạm vi dấu thời gian (Unix epoch int).

Khi người dùng dịch vụ chấm dứt tài khoản của họ, tôi cần xóa tất cả các mục trong bảng, bất kể giá trị phạm vi là bao nhiêu.

Cách được khuyến nghị để thực hiện loại hoạt động này là gì (Hãy nhớ rằng có thể có hàng triệu mục cần xóa)?

Các tùy chọn của tôi, theo như tôi thấy là:

A: Thực hiện thao tác Quét, gọi xóa trên từng mục trả lại, cho đến khi không còn mục nào

B: Thực hiện thao tác BatchGet, một lần nữa gọi xóa trên từng mục cho đến khi không còn mục nào

Cả hai điều này trông rất khủng khiếp đối với tôi vì chúng sẽ mất nhiều thời gian.

Những gì tôi lý tưởng muốn làm là gọi LogTable.DeleteItem (user_id) - Không cung cấp phạm vi và yêu cầu nó xóa mọi thứ cho tôi.

Câu trả lời:


52

Những gì tôi lý tưởng muốn làm là gọi LogTable.DeleteItem (user_id) - Không cung cấp phạm vi và yêu cầu nó xóa mọi thứ cho tôi.

Một yêu cầu dễ hiểu thực sự; Tôi có thể tưởng tượng các hoạt động nâng cao như thế này có thể được nhóm AWS thêm vào theo thời gian (họ có lịch sử bắt đầu với một bộ tính năng hạn chế trước tiên và đánh giá các tiện ích mở rộng dựa trên phản hồi của khách hàng), nhưng đây là những gì bạn nên làm để tránh chi phí quét toàn bộ ít nhất:

  1. Sử dụng Truy vấn thay vì Quét để truy xuất tất cả các mục user_id- điều này hoạt động bất kể khóa chính băm / phạm vi kết hợp đang được sử dụng, vì HashKeyValueRangeKeyCondition là các tham số riêng biệt trong API này và trước đây chỉ nhắm mục tiêu giá trị Thuộc tính của thành phần băm của hỗn hợp khóa chính. .

    • Xin lưu ý rằng bạn sẽ phải xử lý phân trang API truy vấn tại đây như bình thường, hãy xem thông số ExclusiveStartKey :

      Khóa chính của mục để tiếp tục truy vấn trước đó. Một truy vấn trước đó có thể cung cấp giá trị này dưới dạng LastEvalishedKey nếu hoạt động truy vấn đó bị gián đoạn trước khi hoàn thành truy vấn; hoặc do kích thước tập kết quả hoặc tham số Giới hạn. LastEvalonedKey có thể được chuyển trở lại trong một yêu cầu truy vấn mới để tiếp tục hoạt động từ thời điểm đó.

  2. Lặp lại tất cả các mục được trả lại và tạo điều kiện cho DeleteItem như bình thường

    • Cập nhật : Nhiều khả năng BatchWriteItem thích hợp hơn cho trường hợp sử dụng như thế này (xem chi tiết bên dưới).

Cập nhật

Như được ivant đánh dấu , hoạt động BatchWriteItem cho phép bạn đặt hoặc xóa một số mục trên nhiều bảng trong một lệnh gọi API duy nhất [emphasis mine] :

Để tải lên một mục, bạn có thể sử dụng API PutItem và để xóa một mục, bạn có thể sử dụng API DeleteItem. Tuy nhiên, khi bạn muốn tải lên hoặc xóa một lượng lớn dữ liệu, chẳng hạn như tải lên một lượng lớn dữ liệu từ Amazon Elastic MapReduce (EMR) hoặc di chuyển dữ liệu từ cơ sở dữ liệu khác sang Amazon DynamoDB, API này cung cấp một giải pháp thay thế hiệu quả.

Xin lưu ý rằng điều này vẫn có một số hạn chế liên quan, đáng chú ý nhất:

  • Hoạt động tối đa trong một yêu cầu - Bạn có thể chỉ định tổng số tối đa 25 hoạt động đặt hoặc xóa; tuy nhiên, tổng kích thước yêu cầu không được vượt quá 1 MB (tải trọng HTTP).

  • Không phải là hoạt động nguyên tử - Các hoạt động riêng lẻ được chỉ định trong BatchWriteItem là nguyên tử; tuy nhiên nói chung BatchWriteItem là một hoạt động "nỗ lực cao nhất" chứ không phải là một hoạt động nguyên tử. Đó là, trong một yêu cầu BatchWriteItem, một số hoạt động có thể thành công và những hoạt động khác có thể thất bại. [...]

Tuy nhiên, điều này rõ ràng mang lại lợi ích đáng kể tiềm năng cho các trường hợp sử dụng như trường hợp đang sử dụng.


4
Tôi nghĩ rằng nó sẽ làm cho tinh thần để hàng loạt sử dụng delete cho bước thứ hai (đó là "đeo mặt nạ" như một hoạt động hàng loạt ghi )
ivant

1
@ivant - cảm ơn nhiều về gợi ý, chức năng xóa "mặt nạ" này của BatchWriteItem thực sự đã thoát khỏi tôi hồi đó; Tôi đã cập nhật câu trả lời cho phù hợp.
Steffen Opel,

để xóa với BatchWriteItemcác mục cần được chỉ định quaTableWriteItems
Neil

1
Liên kết đến BatchWriteItem hiện là docs.aws.amazon.com/amazondynamodb/latest/APIReference/…
Tony

3
Tôi nhận ra rằng điều này đã cũ và OP đã không đề cập đến SDK ngôn ngữ cụ thể, nhưng trong Python, có một cấp cao batch_writer()như một phần của boto3.resource.TableAPI sẽ "tự động xử lý bộ đệm và gửi các mục theo lô. Ngoài ra, trình viết lô sẽ cũng tự động xử lý bất kỳ mục nào chưa được xử lý và gửi lại khi cần thiết "tức là nó là một trình bao bọc xung quanh BatchWriteItem quản lý các phần gây phiền nhiễu. boto3.amazonaws.com/v1/documentation/api/latest/reference/…
Davos

46

Theo tài liệu DynamoDB, bạn chỉ có thể xóa toàn bộ bảng.

Xem bên dưới:

"Xóa toàn bộ bảng hiệu quả hơn đáng kể so với việc xóa từng mục một, về cơ bản tăng gấp đôi thông lượng ghi khi bạn thực hiện nhiều thao tác xóa như thao tác đặt"

Nếu bạn chỉ muốn xóa một tập hợp con dữ liệu của mình, thì bạn có thể tạo các bảng riêng biệt cho từng tháng, năm hoặc tương tự. Bằng cách này, bạn có thể xóa "tháng trước" và giữ nguyên phần còn lại của dữ liệu.

Đây là cách bạn xóa một bảng trong Java bằng AWS SDK:

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

8
Tôi cũng thích câu trả lời này nhưng hãy thận trọng: điều này có thể tạo ra nhiều bảng trong hệ thống của bạn và chúng tôi trả tiền cho mỗi lần cung cấp bảng. Vì vậy, bạn cần giảm cung cấp sau cuối tháng (nếu bảng của bạn là mỗi tháng) trong khi bảng này không bị xóa.
Sergio MC Figueedlyo

2
đồng ý với câu trả lời này, nó được áp dụng nếu bạn cần xóa tất cả các bản ghi tạo thành bảng, nhưng ở đây người hỏi muốn xóa các mục nhập cơ sở người dùng chứ không phải toàn bộ bảng.
Ihtsham Minhas

1
Việc có một bảng table riêng biệt cho mỗi người dùng sẽ rất tốn kém với giá DynamoDB. Một bàn mỗi tháng thực sự sẽ khiến mọi thứ tồi tệ hơn. Đây rõ ràng là một câu trả lời cho một vấn đề khác, rất cụ thể.
André Werlang

11
Xóa bảng cũng có thể không phải là một tùy chọn hấp dẫn nếu bạn sử dụng cấp phép tự động như CloudFormation để quản lý bảng của mình như một phần của ngăn xếp. Tôi không biết cách đơn giản để khiến CloudFormation tạo lại bảng mà bạn đã xóa bằng tay.
brabster

2
Cách tiếp cận này mất khá nhiều thời gian để xóa và tạo lại (khi cần) bảng, khiến nó không khả dụng trong toàn bộ thời gian. Câu hỏi nêu rõ việc xóa dữ liệu người dùng, điều này sẽ không thực tế khi chia thành các bảng riêng biệt cho mỗi người dùng.
André Werlang

13

Nếu bạn muốn xóa các mục sau một thời gian, chẳng hạn như sau một tháng, chỉ cần sử dụng tùy chọn Time To Live. Nó sẽ không tính đơn vị ghi.

Trong trường hợp của bạn, tôi sẽ thêm ttl khi nhật ký hết hạn và để lại chúng sau khi người dùng bị xóa. TTL sẽ đảm bảo rằng các bản ghi được xóa cuối cùng.

Khi Thời gian tồn tại được bật trên bảng, công việc nền sẽ kiểm tra thuộc tính TTL của các mục để xem chúng đã hết hạn chưa.

DynamoDB thường xóa các mục đã hết hạn trong vòng 48 giờ sau khi hết hạn. Khoảng thời gian chính xác mà trong đó một mục thực sự bị xóa sau khi hết hạn là cụ thể cho bản chất của khối lượng công việc và kích thước của bảng. Các mục đã hết hạn và chưa bị xóa sẽ vẫn hiển thị trong các lần đọc, truy vấn và quét. Các mục này vẫn có thể được cập nhật và cập nhật thành công để thay đổi hoặc loại bỏ thuộc tính hết hạn sẽ được thực hiện.

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


thêm TTL là một "cập nhật" (hoạt động ghi). Tôi không chắc có lợi gì khi thực hiện "cập nhật" thay vì "xóa".
Tomer

bạn có thể chèn dữ liệu đó bằng ghi gốc và cập nhật bằng bất kỳ hành động cập nhật nào khác. Tất nhiên, nó không phải là một tùy chọn nếu bạn có một loạt dữ liệu và sau đó bạn muốn xóa nó. Nhưng đây là một tùy chọn hợp lệ cho các trường hợp bạn có thể có ttl cho dữ liệu bạn chèn hoặc cập nhật.
Lukas Liesis

1
Tôi đồng ý, nếu TTL đã được định cấu hình và quá trình dọn dẹp có thể đợi đến 48 giờ thì đó chắc chắn là lựa chọn tối ưu. Tôi xin lỗi nếu tôi không rõ ràng.
Tomer

4

Câu trả lời của câu hỏi này phụ thuộc vào số lượng mặt hàng và kích thước của chúng và ngân sách của bạn. Tùy thuộc vào đó, chúng tôi có 3 trường hợp sau:

1- Số lượng mục và kích thước các mục trong bảng không nhiều lắm. thì như Steffen Opel đã nói bạn có thể Sử dụng Truy vấn thay vì Quét để truy xuất tất cả các mục cho user_id và sau đó lặp lại tất cả các mục được trả lại và tạo điều kiện DeleteItemhoặcBatchWriteItem. Nhưng hãy nhớ rằng bạn có thể đốt cháy rất nhiều công suất thông lượng ở đây. Ví dụ: hãy xem xét một tình huống mà bạn cần xóa 1000 mục khỏi bảng DynamoDB. Giả sử rằng mỗi mục có kích thước 1 KB, dẫn đến khoảng 1MB dữ liệu. Tác vụ xóa hàng loạt này sẽ yêu cầu tổng cộng 2000 đơn vị khả năng ghi cho truy vấn và xóa. Để thực hiện tải dữ liệu này trong vòng 10 giây (thậm chí không được coi là nhanh trong một số ứng dụng), bạn sẽ cần đặt thông lượng ghi được cung cấp của bảng thành 200 đơn vị khả năng ghi. Như bạn có thể thấy nó có thể sử dụng theo cách này nếu nó cho số lượng mặt hàng ít hơn hoặc các mặt hàng kích thước nhỏ.

2- Chúng ta có rất nhiều đồ hoặc đồ rất lớn trong bàn và có thể cất theo thời gian vào các bàn khác nhau. Sau đó, như jonathan đã nói, bạn chỉ có thể xóa bảng. điều này tốt hơn nhiều nhưng tôi không nghĩ rằng nó phù hợp với trường hợp của bạn. Vì bạn muốn xóa tất cả dữ liệu người dùng bất kể thời gian tạo nhật ký là gì, vì vậy trong trường hợp này, bạn không thể xóa một bảng cụ thể. nếu bạn muốn có một bảng riêng cho từng người dùng thì tôi đoán nếu số lượng người dùng nhiều thì nó sẽ đắt như vậy và nó không thực tế cho trường hợp của bạn.

3- Nếu bạn có nhiều dữ liệu và bạn không thể chia dữ liệu nóng và lạnh của mình thành các bảng khác nhau và bạn cần thực hiện xóa quy mô lớn thường xuyên thì rất tiếc DynamoDB không phải là một lựa chọn tốt cho bạn. Nó có thể trở nên đắt hơn hoặc rất chậm (tùy thuộc vào ngân sách của bạn). Trong những trường hợp này, tôi khuyên bạn nên tìm một cơ sở dữ liệu khác cho dữ liệu của bạn.


0

Cách tiếp cận của tôi để xóa tất cả các hàng khỏi bảng i DynamoDb chỉ là kéo tất cả các hàng ra khỏi bảng, sử dụng DynamoDbs ScanAsync và sau đó cung cấp danh sách kết quả cho DynamoDbs AddDeleteItems. Mã dưới đây trong C # hoạt động tốt đối với tôi.

        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();
    }

Lưu ý: Xóa bảng rồi tạo lại từ bảng điều khiển web có thể gây ra sự cố nếu sử dụng YAML / CloudFront để tạo bảng.


0

Chúng tôi không có tùy chọn để cắt bớt bảng động. chúng ta phải bỏ bảng và tạo lại. Tính phí DynamoDB dựa trên ReadCapacityUnits & WriteCapacityUnits. Nếu chúng ta xóa tất cả các mục bằng chức năng BatchWriteItem, nó sẽ sử dụng WriteCapacityUnits. Vì vậy, tốt hơn là xóa các bản ghi cụ thể hoặc xóa bảng và bắt đầu lại.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.