Hỏi việc xóa dữ liệu trong một collection rất lớn trong mongodb?

Em chào các anh chị.
Hiện tại em đang làm trong một dự án và gặp vấn về với việc xóa dữ liệu cũ.
Em đang có 1 collection trong mongodb có các trường chính sau:
id, a, b ,c ,d , bet_date ( các trường a, b, c, d có kiểu dữ liệu là số thực, id có kiểu dữ liệu số nguyên, bet_date có kiểu dữ liệu date time )
Collections này đã được đánh index theo id và bet_date.

id là id của user, có tầm 30.000 id trong collection này ( Tức trung bình mỗi id có tầm 37000 bản ghi )

Hiện tại collection này đang có số bản ghi rất rất lớn: tầm 1.100.000.000 ( Hơn 1 tỉ bản ghi )

Em đang muốn xóa những dữ liệu lâu hơn 30 ngày ( do đó em cần xóa tầm 700 triệu bản ghi )

Em đã thử cách sau:
Em tìm theo từng id, sau đó xóa những bản ghi dưới 30 của id đó. Nhưng em đã thử chạy xóa cho 1 id thì nó mất tận từ 2-4 phút 1 lần xóa cho 1 con. Như vậy tốc độ xóa như thể không thể kịp thời với tốc độ ghi thêm vào dữ liệu.

Có anh chị nào có kinh nghiệm trong việc xóa một lượng dữ liệu lớn thế này không ạ ?

Em cảm ơn.

Hi Mạnh,

Tớ có 1 số điều cần verify trước khi thảo luận về solution cho vấn đề của cậu.

  1. Service của cậu có vấn đề gì với service downtime không?
  2. Mỗi ngày, ước tính có bao nhiêu new records cho collection đó của cậu?
  3. Service của cậu có bất cứ use case nào cần sử dụng dữ liệu cũ không? Ví dụ: cho việc phân tích, hoặc troubleshooting…
  4. Server của cậu còn nhiều bộ nhớ không? Có đủ chứa toàn bộ dữ liệu này ko?
  5. Nếu dữ liệu của cậu bị corrupted sau task này, liệu cậu có backup server không?

Mong nhận được phản hồi của cậu trước khi chúng ta bàn tiếp về solution.

4 Likes

Dạ, em cung cấp thông tin như sau:

  1. Server của em mỗi ngày có 4 tiếng off, còn lại không được phép off đi.
  2. Mỗi ngày phát sinh tầm 12 triệu bản ghi ạ, và trong tương lai có thể lớn hơn.
  3. Dữ liệu này phục vụ việc hiển thị ra cho người dùng xem
  4. Server còn rất nhiều bộ nhớ ạ. Bảng này không quá nặng ( chỉ tầm vài chục gb, nhưng tổng số bản ghi lại rất lớn )
  5. Bên mình đã có dữ liệu backup. Nhưng khá hạn chế việc này thì dữ liệu back up quá lớn ( Tầm 400 triệu bản ghi )

Mong anh/chị có thể giúp được em :smiley:

1 Like

Hiện tại em đang nghĩ ra solution thế này.

Việc xóa thì rất rất lâu nhưng việc lấy dữ liệu ra và insert dữ liệu vào rất nhanh. Nên em nghĩ sẽ lấy những dữ liệu cần thiết và insert vào một collection mới. Ví dụ collection cũ là abc thì collection mới sẽ là abc_new.

Mỗi id sẽ mất tầm 8s để copy dữ liệu, 30000 id sẽ mất tầm 30000*8/3600 = 67 tieesng. Thời gian thực tế có thể nhỏ hơn khá nhiều vì không phải id nào cũng có nhiều dữ liệu. Mỗi ngày em chuyển đổi 3.5 tiếng như vậy thì tổng thời gian chuyển đổi sang collection mới hết tầm 20 ngày.

Sau khi chuyển đổi xong, em sẽ drop collection cũ đi, đổi tên collection mới thành cũ.

1 Like

Hi cậu,
Cảm ơn về phản hồi của cậu nhé :smiley:

Lý do tớ hỏi cậu 1 số thông tin trước khi đưa ra solution là để hiểu thêm về vấn đề của cậu. Solution nên được design dựa trên problem của cậu.
Qua những trao đổi của cậu, tớ có thể thấy 1 số điểm cần chú ý:

  1. Tốc độ thêm dữ liệu mới của service khá cao -> Cậu sẽ phải lặp lại công việc dọn dẹp thường xuyên.
  2. Service cho phép downtime -> cậu có thể lên kế hoạch cho việc dọn dẹp
  3. Server có nhiều bộ nhớ -> cậu không gặp vấn đề gì khi tạo 1 collection mới chứa 1 phần dữ liệu cũ
  4. Đã có backup -> nếu có vấn đề, cậu có thể fallback.
  5. Dữ liệu chỉ phục vụ hiển thị -> cậu có thể design policy delete/archive dữ liệu định kỳ.

Tớ đồng ý với cậu về solution tạo collection mới, nó có lẽ sẽ hiệu quả hơn so với việc xoá data cũ. Tuy nhiên, tớ nghĩ cậu có thể mở rộng solution của cậu hơn chút.
Dựa trên những điều rút ra ở trên, tớ có 1 số recommend cho cậu, hi vọng nó sẽ giúp cậu đưa ra solution và planning phù hợp:

  1. Bởi vì mỗi ngày cậu có tương đối nhiều record mới, tớ nghĩ cậu nên cân nhắc maintain 2 collections song song cho application của cậu.
    Tức là mỗi khi cậu có record mới ở collection cũ, cậu insert nó ở collection mới luôn.
    Cậu có thể giữ mối quan hệ này cho tới khi migrate thành công toàn bộ collection cũ sang collection mới, và giảm đc sự sai khác khi cậu ko thể delete kịp.
  2. Sau khi migrate xong, cậu nên design policy để xóa/archive dữ liệu cũ. Do dữ liệu của cậu phát sinh rất nhiều trong 1 ngày, tớ nghĩ đó là transaction data (có vẻ như là giao dịch cá độ), nên tớ nghĩ cậu sẽ gặp vấn đề tương tự trong tương lai.
    Tuỳ vào độ quan trọng của những dữ liệu đó mà cậu chọn sẽ xoá/archive phù hợp (nếu dữ liệu đó là các transaction liên quan tới tiền nong hoặc liên quan tới luật pháp, cậu nên archive, do sau này khi có tranh chấp, cậu sẽ cần prove).
  3. Cậu có thể design 1 batch chạy vào thời điểm service off, để copy dữ liệu cũ sang collection mới, do cậu cần làm điều đó 20 ngày liền hoặc có thể hơn.
  4. Sau khi quá trình migrate hoàn tất và cậu đã drop collection và switch sang dùng collection mới, tớ recommend cậu nên design 1 batch để xoá/archive các dữ liệu cũ định kỳ.

Tớ hi vọng những suggestion trên đây có thể cho cậu thêm ý tưởng mới cho vấn đề của cậu.

5 Likes
  • Đối với Collection mới, bạn có thể thêm trường TTL để database tự delete nó sau thời gian expired, khỏi phải làm gì khác.
    Một phương án khác là dùng Capped Collection, tạo 1 fixed size collection, tràn thì nó tự bỏ mấy thằng cũ nhất, theo FIFO.

  • Đối với Collection cũ, bạn có thể thử Bulk remove

  • Ngoài ra, với dữ liệu lớn, khi dùng find thì theo ý kiến cá nhân của mình bạn nên giới hạn kích thước trả về bằng limit như vậy thời gian xử lý có thể cải thiện.

3 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?