2012-01-13 43 views
5

Câu hỏi này dành cho tất cả chuyên gia NoSQL và đặc biệt mongoDB ở đó. Tôi bắt đầu bằng cách thiết kế một DB quan hệ cho một dự án nhưng khách hàng muốn chúng tôi sử dụng một DB có thể dễ dàng mở rộng quy mô. Để đạt được điều này, chúng tôi đã quyết định sử dụng mongoDB. Những ngày này tôi đang gặp khó khăn trong việc lập bản đồ mô hình quan hệ của tôi cho NoSQL. Tôi có một bảng người dùng trong đó có một mối quan hệ nhiều-nhiều với rất nhiều bảng khác như minh họa dưới đây:Quan hệ với cơ sở dữ liệu NoSQL

relational DB

Tôi có một vài lựa chọn khi chuyển đổi nó cho MongoDB:

Tùy chọn 1 (với hàng hoàn toàn trong sử dụng):

users:{ 
    _id:<user_id>, 
    battles:{[battle1, battle2, ...]}, 
    items:{[item1, item2, ...]}, 
    locations:{[location1, location2, ...]}, 
    units:{[unit1, unit2, ...]}, 
} 

battles:{ 
    <battle_info> 
} 

locations:{ 
    <location_info> 
} 

units:{ 
    <units_info> 
} 

items:{ 
    <items_info> 
} 

OPTION2 (chỉ với phím nước ngoài trong người sử dụng):

users:{ 
    _id:<user_id>, 
    battles:{[battle1_id, battle2_id, ...]}, 
    items:{[item1_id, item2_id, ...]}, 
    locations:{[location1_id, location2_id, ...]}, 
    units:{[unit1_id, unit2_id, ...]}, 
} 

battles:{ 
    <battle_info> 
} 

locations:{ 
    <location_info> 
} 

units:{ 
    <units_info> 
} 

items:{ 
    <items_info> 
} 

Lựa chọn 3 (id người dùng trong các bảng khác):

users:{ 
    _id:<user_id>, 
} 

battles:{ 
    <battle_info>, 
    user:{[user1_id, user2_id, ...]} 
} 

locations:{ 
    <location_info>, 
    user:{[user1_id, user2_id, ...]} 
} 

units:{ 
    <units_info>, 
    user:{[user1_id, user2_id, ...]} 
} 

items:{ 
    <items_info>, 
    user:{[user1_id, user2_id, ...]} 
} 

Lựa chọn 1 có rất nhiều sự trùng lặp như chúng tôi có thêm hàng hoàn toàn của các bảng khác. Một vấn đề tôi thấy ở đây là nếu một mục hoặc trận chiến nào đó được cập nhật, chúng ta sẽ phải tìm tất cả các lần xuất hiện của nó trong bảng người dùng và cập nhật chúng. Nhưng điều này mang lại cho chúng ta lợi thế của việc luôn có một đối tượng người dùng hoàn chỉnh có thể được trao cho ứng dụng của khách hàng tại thời điểm đăng nhập.

Tùy chọn 2 có quan hệ hơn khi chúng tôi chỉ có mongoIds các bảng khác trong bảng người dùng. Lợi thế của các tùy chọn này là việc cập nhật một trận chiến hoặc mục không có nhiều chi phí vì các hàng được tham chiếu không được sao chép. Mặt khác, khi người dùng đăng nhập, chúng tôi sẽ phải tìm tất cả các đơn vị được tham chiếu, trận chiến, vật phẩm và vị trí để phản hồi với đối tượng người dùng hoàn chỉnh.

Tùy chọn 3 nằm đối diện với tùy chọn 2 trong đó mongoBảng người dùng được lưu giữ trong các bảng khác. Tùy chọn này không hấp dẫn tôi nhiều.

Tôi thực sự đánh giá cao ai đó có thể hướng dẫn tôi hoặc đưa ra mô hình tốt hơn.

Edit:

Về cơ bản đây là một trò chơi MMORPG nơi nhiều khách hàng ứng dụng sẽ kết nối đến máy chủ thông qua webservices. Chúng tôi đã có một db cục bộ tại máy khách để lưu trữ dữ liệu. Tôi muốn một mô hình mà qua đó máy chủ có thể đáp ứng với một đối tượng người dùng hoàn chỉnh và sau đó cập nhật hoặc chèn dữ liệu thay đổi trên ứng dụng khách.

+0

"tốt hơn" là vấn đề của mục đích. Mẫu truy cập của bạn cho dữ liệu này là gì? –

+0

về cơ bản đây là trò chơi MMORPG nơi nhiều ứng dụng khách hàng sẽ kết nối với máy chủ thông qua dịch vụ web. Chúng tôi đã có một db cục bộ tại máy khách để lưu trữ dữ liệu. Tôi muốn một mô hình thông qua đó máy chủ có thể đáp ứng với một đối tượng người dùng hoàn chỉnh và sau đó cập nhật hoặc chèn dữ liệu thay đổi trên ứng dụng của khách hàng – umair

+8

Cơ sở dữ liệu quan hệ có khả năng mở rộng quy mô ... sự khác biệt phải là loại dữ liệu mà chúng được dự kiến ​​sẽ giữ, không phải là một định kiến ​​sai lầm rằng RDB chỉ dành cho dữ liệu nhỏ, mongodb cho lớn –

Trả lời

5

Thứ nhất, NoSQL là không một kích thước phù hợp với tất cả. Trong SQL, hầu như mọi mối quan hệ 1: N và M: N đều được mô hình hóa theo cùng một cách. Triết lý NoSQL là cách bạn mô hình hóa dữ liệu phụ thuộc vào dữ liệu và các mẫu sử dụng của nó.

Thứ hai, tôi đồng ý với Mark Baker: Mở rộng quy mô là khó khăn và đạt được bằng cách nới lỏng các ràng buộc.Nó không phải là vấn đề công nghệ. Tôi thích làm việc với MongoDB, nhưng vì lý do khác (không cần phải viết mã SQL xấu xí, không có nhu cầu phức tạp, ORM cồng kềnh, vv)

Bây giờ chúng ta hãy xem xét các lựa chọn của bạn: Lựa chọn 1 bản nhiều dữ liệu hơn cần thiết. Bạn thường phải làm mất chuẩn hóa một số dữ liệu, nhưng không bao giờ hết. Nếu vậy, sẽ rẻ hơn khi tìm nạp đối tượng được tham chiếu.

Tùy chọn 2/3 chúng rất giống nhau. Chìa khóa ở đây là: ai đang viết? Bạn không muốn nhiều khách hàng có quyền truy cập ghi vào cùng một tài liệu, bởi vì điều đó sẽ buộc bạn phải sử dụng cơ chế khóa và/hoặc hạn chế bản thân chỉ cho các hoạt động sửa đổi. Vì vậy, tùy chọn 2 có lẽ tốt hơn 3. Tuy nhiên, nếu A tấn công B, họ cũng sẽ kích hoạt một ghi cho người dùng B, vì vậy bạn phải chắc chắn rằng bài viết của bạn được an toàn.

Lựa chọn 4 denormalization từng phần: đối tượng sử dụng của bạn có vẻ là quan trọng nhất, vậy làm thế nào về điều này:

user { 
battles : [ {"Name" : "The battle of foo", "Id" : 4354 }, ... ] 
... 
} 

Điều này sẽ làm cho nó dễ dàng hơn để hiển thị ví dụ một trang tổng quan người dùng, bởi vì bạn không cần biết tất cả các chi tiết trong trang tổng quan. Lưu ý: cấu trúc dữ liệu sau đó được ghép nối với các chi tiết của bản trình bày.

Tùy chọn 5 Dữ liệu trên các cạnh. Thông thường, các mối quan hệ cần phải giữ dữ liệu cũng như:

user { 
battles : [ {"Name" : "The battle of foo", "unitsLost" : 54, "Id" : 34354 }, ... ] 
} 

đây, unitsLost là cụ thể cho người sử dụng và các trận chiến, vì thế mà dữ liệu nằm trên các cạnh của đồ thị. Trái ngược với tên của trận chiến, dữ liệu này không được chuẩn hóa.

Tùy chọn 6 Bộ sưu tập của trình liên kết. Tất nhiên, 'dữ liệu cạnh' như vậy có thể phát triển rất lớn và thậm chí có thể gọi cho một bộ sưu tập riêng biệt (bộ sưu tập liên kết). Điều này loại bỏ hoàn toàn vấn đề của các khóa truy cập:

user { 
    "_id" : 3443 
} 

userBattles { 
    userId : 3443, 
    battleId : 4354, 
    unitsLost : 43, 
    itemsWon : [ <some list > ], 
    // much more data 
} 

Điều nào là tốt nhất tùy thuộc vào rất nhiều chi tiết về đơn đăng ký của bạn. Nếu người dùng thực hiện nhiều lần nhấp chuột (tức là bạn có giao diện chi tiết), bạn có thể chia nhỏ các đối tượng như trong tùy chọn 4 hoặc 6. Nếu bạn thực sự cần tất cả dữ liệu trong một đợt, việc không chuẩn hóa từng phần không giúp ích gì, vì vậy tùy chọn 2 sẽ thích hợp hơn. Hãy ghi nhớ vấn đề nhiều người viết.

+1

Cảm ơn câu trả lời chi tiết. Bạn đã thực hiện một điểm thú vị mà không phải tất cả các mối quan hệ nhiều-nhiều sẽ có cùng cấu trúc trong NoSQL. Tôi nghĩ rằng tôi sẽ phải cấu trúc chúng theo nhu cầu của tôi. – umair

1

Tùy chọn 2 là cách để đi.

Nếu bạn làm điều đó trong RDB, tại một thời điểm nào đó (khi bạn phải bắt đầu mở rộng theo chiều ngang), bạn cũng cần bắt đầu loại bỏ các phép nối SQL và nối dữ liệu ở cấp ứng dụng.

Thậm chí 10gen khuyến cáo sử dụng "bằng tay" id tham khảo: http://www.mongodb.org/display/DOCS/Database+References

Các vấn đề liên quan