MongoDB
 sql >> Cơ Sở Dữ Liệu >  >> NoSQL >> MongoDB

Người theo dõi - thiết kế cơ sở dữ liệu mongodb

Tôi đồng ý với quan điểm chung của các câu trả lời khác rằng đây là ranh giới vấn đề quan hệ.

Chìa khóa của mô hình dữ liệu MongoDB là khả năng ghi, nhưng điều đó có thể phức tạp đối với trường hợp sử dụng này, chủ yếu là do việc ghi sổ kế toán sẽ được yêu cầu nếu bạn muốn liên kết trực tiếp người dùng với các mục (thay đổi đối với một nhóm được theo sau bởi nhiều người dùng sẽ phải chịu một số lượng lớn các lần ghi và bạn cần một số nhân viên thực hiện việc này).

Hãy điều tra xem mô hình đọc nhiều có không thể áp dụng được ở đây hay chúng ta đang thực hiện tối ưu hóa quá sớm.

Phương pháp tiếp cận đã đọc

Mối quan tâm chính của bạn là trường hợp sử dụng sau:

vấn đề hiệu suất thực sự có thể là khi tôi muốn nhận tất cả các nhóm mà người dùng đang theo dõi cho một mục cụ thể [...] vì sau đó tôi phải tìm tất cả các nhóm mà người dùng đang theo dõi và từ đó tìm tất cả item_groups với group_id $in và id mặt hàng.

Hãy cùng mổ xẻ điều này:

  • Nhận tất cả các nhóm mà người dùng đang theo dõi

    Đó là một truy vấn đơn giản:db.followers.find({userId : userId}) . Chúng tôi sẽ cần một chỉ mục trên userId điều này sẽ làm cho thời gian chạy của hoạt động này là O (log n), hoặc nhanh như chớp ngay cả đối với n lớn.

  • từ đó tìm tất cả item_groups có group_id $in và id mặt hàng

    Bây giờ đây là phần phức tạp hơn. Hãy giả sử một chút rằng các mục không có khả năng là một phần của một số lượng lớn các nhóm. Sau đó, một chỉ mục kết hợp { itemId, groupId } sẽ hoạt động tốt nhất, vì chúng tôi có thể giảm đáng kể ứng viên được đặt thông qua tiêu chí đầu tiên - nếu một mục chỉ được chia sẻ trong 800 nhóm và người dùng đang theo dõi 220 nhóm, mongodb chỉ cần tìm giao điểm của những nhóm này, tương đối dễ dàng vì cả hai bộ nhỏ.

Tuy nhiên, chúng ta sẽ cần phải đi sâu hơn điều này:

Cấu trúc dữ liệu của bạn là có thể là của một mạng phức tạp . Mạng phức tạp có nhiều loại, nhưng sẽ hợp lý nếu giả sử đồ thị người theo dõi của bạn gần như không có tỷ lệ, đây cũng là trường hợp xấu nhất. Trong một mạng miễn phí quy mô, một số lượng rất nhỏ các nút (người nổi tiếng, siêu đại gia, Wikipedia) thu hút rất nhiều 'sự chú ý' (tức là có nhiều kết nối), trong khi số lượng lớn hơn nhiều nút gặp khó khăn trong việc thu hút sự chú ý như nhau. kết hợp .

Các nút nhỏ không có lý do gì để lo ngại , các truy vấn ở trên, bao gồm cả các chuyến đi khứ hồi đến cơ sở dữ liệu nằm trong phạm vi 2ms trên máy phát triển của tôi trên tập dữ liệu có hàng chục triệu kết nối và> 5GB dữ liệu. Bây giờ tập dữ liệu đó không phải là lớn, nhưng bất kể bạn chọn công nghệ nào, sẽ bị ràng buộc về RAM vì các chỉ số phải nằm trong RAM trong mọi trường hợp (vị trí dữ liệu và khả năng phân tách trong mạng nói chung là kém) và kích thước giao điểm được đặt là nhỏ theo định nghĩa. Nói cách khác:chế độ này bị chi phối bởi tắc nghẽn phần cứng.

Còn về supernodes mặc dù?

Vì đó chỉ là phỏng đoán và tôi rất quan tâm đến các mô hình mạng, tôi đã tự do triển khai một công cụ mạng được đơn giản hóa đáng kể dựa trên mô hình dữ liệu của bạn để thực hiện một số phép đo. (Xin lỗi nó bằng C #, nhưng việc tạo ra các mạng có cấu trúc tốt là đủ khó bằng ngôn ngữ mà tôi thông thạo nhất ...).

Khi truy vấn siêu cực, tôi nhận được kết quả trong phạm vi đỉnh 7ms (Đó là trên 12 triệu mục nhập trong 1,3 GB db, với nhóm lớn nhất có 133.000 mục trong đó và người dùng theo dõi 143 nhóm.)

Giả định trong đoạn mã này, số lượng nhóm được theo dõi bởi một người dùng không lớn, nhưng điều đó có vẻ hợp lý ở đây. Nếu không, tôi sẽ chuyển sang cách tiếp cận ghi nhiều.

Hãy thoải mái chơi với mã. Thật không may, nó sẽ cần một chút tối ưu hóa nếu bạn muốn thử điều này với hơn một vài GB dữ liệu, vì nó chỉ đơn giản là không được tối ưu hóa và thực hiện một số tính toán rất kém hiệu quả ở đây (đặc biệt là xáo trộn ngẫu nhiên có trọng số beta có thể được cải thiện ).

Nói cách khác:Tôi sẽ không lo lắng về hiệu suất của phương pháp đọc nhiều chưa . Vấn đề thường không phải là số lượng người dùng tăng lên mà là người dùng sử dụng hệ thống theo những cách không mong muốn.

Phương pháp tiếp cận bằng văn bản

Cách tiếp cận thay thế có thể là đảo ngược thứ tự liên kết:

UserItemLinker
{
 userId,
 itemId,
 groupIds[]  // for faster retrieval of the linker. It's unlikely that this grows large
}

Đây có lẽ là mô hình dữ liệu có khả năng mở rộng cao nhất, nhưng tôi sẽ không sử dụng nó trừ khi chúng ta đang nói về lượng dữ liệu KHỔNG LỒ trong đó sharding là một yêu cầu quan trọng. Sự khác biệt chính ở đây là giờ đây chúng ta có thể phân chia dữ liệu một cách hiệu quả bằng cách sử dụng userId như một phần của khóa phân đoạn. Điều đó giúp song song hóa các truy vấn, phân đoạn một cách hiệu quả và cải thiện vị trí dữ liệu trong các kịch bản nhiều trung tâm dữ liệu.

Điều này có thể được kiểm tra bằng một phiên bản testbed phức tạp hơn, nhưng tôi chưa tìm thấy thời gian và thành thật mà nói, tôi nghĩ rằng nó quá mức cần thiết đối với hầu hết các ứng dụng.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Quản lý AWS:Cách tiết kiệm 30% chi phí lưu trữ MongoDB của bạn

  2. Thông báo lỗi tùy chỉnh với Mongoose

  3. Toán tử tổng hợp MongoDB $ sortByCount

  4. Dừng mongodb bỏ qua các ký tự đặc biệt?

  5. Cách chính xác để bắt đầu một dịch vụ mongod trên linux / OS X là gì?