Làm cách nào để bạn theo dõi quan hệ bản ghi trong NoSQL?


117

Tôi đang cố gắng tìm ra các khóa và chỉ mục ngoại tương đương trong cơ sở dữ liệu NoSQL KVP hoặc Document. Vì không có bảng tổng hợp (để thêm các khóa đánh dấu mối quan hệ giữa hai đối tượng) nên tôi thực sự bối rối về cách bạn có thể truy xuất dữ liệu theo cách hữu ích cho các trang web bình thường.

Giả sử tôi có một người dùng, và người dùng này để lại nhiều bình luận trên khắp trang web. Cách duy nhất tôi có thể nghĩ ra để theo dõi nhận xét của người dùng đó là

  1. Nhúng chúng vào đối tượng người dùng (có vẻ khá vô dụng)
  2. Tạo và duy trì một user_id:commentsgiá trị chứa danh sách khóa của mỗi nhận xét [nhận xét: 34, nhận xét: 197, v.v.] để tôi có thể tìm nạp chúng khi cần.

Tuy nhiên, lấy ví dụ thứ hai, bạn sẽ sớm gặp phải một bức tường gạch khi bạn sử dụng nó để theo dõi những thứ khác, chẳng hạn như khóa có tên "active_comments" có thể chứa 30 triệu id trong đó, khiến cho việc truy vấn mỗi trang phải tốn một TON chỉ để biết một số gần đây bình luận tích cực. Nó cũng sẽ rất dễ xảy ra các điều kiện đua vì nhiều trang có thể cố gắng cập nhật nó cùng một lúc.

Làm cách nào để theo dõi các quan hệ như sau trong cơ sở dữ liệu NoSQL?

  • Tất cả nhận xét của người dùng
  • Tất cả các bình luận hoạt động
  • Tất cả các bài đăng được gắn thẻ [từ khóa]
  • Tất cả học sinh trong một câu lạc bộ - hoặc tất cả các câu lạc bộ mà một học sinh tham gia

Hay tôi đang nghĩ về điều này không đúng?


Không có một cách nào để làm điều đó trong cơ sở dữ liệu NoSQL, câu hỏi này thay vì hỏi tôi làm thế nào để theo dõi các mối quan hệ trong các chương trình C.
stonemetal,

3
Wow, sau đó tôi đoán cường điệu về việc NoSQL thay thế RDBMS là không thể.
Xeoncross

11
Có, NoSQL chắc chắn là quá nhiều. Tôi không nói rằng các công nghệ mới không hữu ích trong những trường hợp thích hợp, nhưng thật nực cười khi nghĩ rằng chúng sẽ thay thế RDBMS. Xem en.wikipedia.org/wiki/Hype_cycle
Bill Karwin

1
Bạn sẽ không chỉ có một bộ sưu tập 'người dùng' và một bộ sưu tập các bình luận. Và sau đó, mỗi nhận xét chỉ là một thuộc tính 'tác giả' có giá trị là một tham chiếu trở lại id người dùng?
CodeFinity

Câu trả lời:


186

Tất cả các câu trả lời cho cách lưu trữ nhiều-nhiều liên kết theo "cách NoSQL" giảm xuống cùng một thứ: lưu trữ dữ liệu dư thừa.

Trong NoSQL, bạn không thiết kế cơ sở dữ liệu của mình dựa trên mối quan hệ giữa các thực thể dữ liệu. Bạn thiết kế cơ sở dữ liệu của mình dựa trên các truy vấn mà bạn sẽ chạy với nó. Sử dụng cùng tiêu chí mà bạn sẽ sử dụng để chuẩn hóa cơ sở dữ liệu quan hệ: nếu dữ liệu quan trọng hơn để có sự gắn kết (hãy nghĩ về các giá trị trong danh sách được phân tách bằng dấu phẩy thay vì bảng chuẩn hóa), thì hãy làm theo cách đó.

Nhưng điều này chắc chắn sẽ tối ưu hóa cho một loại truy vấn (ví dụ: nhận xét của bất kỳ người dùng nào cho một bài báo nhất định) với chi phí của các loại truy vấn khác (nhận xét cho bất kỳ bài viết nào của một người dùng nhất định). Nếu ứng dụng của bạn có nhu cầu để cả hai loại truy vấn được tối ưu hóa như nhau, bạn không nên chuẩn hóa lại. Và tương tự như vậy, bạn không nên sử dụng giải pháp NoSQL nếu bạn cần sử dụng dữ liệu theo cách quan hệ.

Có một rủi ro với việc không chuẩn hóa và dư thừa là các bộ dữ liệu dư thừa sẽ không đồng bộ với nhau. Đây được gọi là sự bất thường . Khi bạn sử dụng cơ sở dữ liệu quan hệ được chuẩn hóa, RDBMS có thể ngăn chặn sự bất thường. Trong cơ sở dữ liệu không chuẩn hóa hoặc trong NoSQL, bạn có trách nhiệm viết mã ứng dụng để ngăn chặn sự bất thường.

Người ta có thể nghĩ rằng sẽ thật tuyệt khi một cơ sở dữ liệu NoSQL thực hiện công việc khó khăn trong việc ngăn chặn sự bất thường cho bạn. Có một mô hình có thể làm được điều này - mô hình quan hệ.


20
"Bạn không nên sử dụng giải pháp NoSQL nếu bạn cần sử dụng dữ liệu theo cách quan hệ" - Vậy làm thế nào để những người khác đang chạy NoSQL thoát khỏi nó? Làm thế nào bạn có thể biết tất cả các cách bạn sẽ truy vấn dữ liệu khi lần đầu tiên thiết kế ứng dụng của mình? Fox Ví dụ, tôi có thể muốn bình luận gần đây, ý kiến của người dùng, ý kiến của thẻ, bình luận cho một bài nào đó, ý kiến đánh dấu là spam, bình luận tích cực, ý kiến đánh giá cao nhất vv
Xeoncross

14
Chính xác - không có cái gọi là "nó chỉ hoạt động" như những người ủng hộ NoSQL muốn tuyên bố. Hoặc bạn thực hiện một loạt các phân tích trước cho mô hình dữ liệu quan hệ của mình hoặc bạn thực hiện một loạt các phân tích trước cho các truy vấn ưu tiên hàng đầu của mình hoặc bạn thực hiện một loạt các cấu trúc lại tốn kém trong suốt dự án khi bạn phát hiện ra phần nào trong thiết kế của mình không có đủ phân tích trước.
Bill Karwin

1
Nếu chúng ta lưu trữ dữ liệu dư thừa, chúng ta nên cập nhật mọi thứ như thế nào? Ví dụ, thay đổi tên của anh ấy và anh ấy đã viết một số nhận xét. Tên của anh ấy đã được thay đổi trong bộ sưu tập người dùng, nhưng làm thế nào để thay đổi tất cả các tên được lưu trữ dư thừa trong bộ sưu tập nhận xét?
Mohammad Kermani

3
@ M98, À, bạn đã tìm ra điểm yếu trong chiến lược này. Bạn phải biết về tất cả những nơi bạn cần cập nhật và sau đó viết mã trong ứng dụng của bạn để cập nhật tất cả chúng khi bạn cập nhật bất kỳ nơi nào. Chúc may mắn!
Bill Karwin

2
Vấn đề tương tự cũng tồn tại đối với cơ sở dữ liệu quan hệ không chuẩn hóa .
Bill Karwin

5

Cách tiếp cận couchDB đề xuất phát ra các lớp nội dung phù hợp trong giai đoạn lập bản đồ và tóm tắt nó lại. Vì vậy, bạn có thể ánh xạ tất cả các nhận xét và phát ra 1cho người dùng nhất định và sau đó chỉ in ra những nhận xét đó. Tuy nhiên, nó sẽ yêu cầu rất nhiều dung lượng lưu trữ trên đĩa để xây dựng chế độ xem liên tục của tất cả dữ liệu có thể theo dõi trong couchDB. btw họ cũng có trang wiki này về các mối quan hệ: http://wiki.apache.org/couchdb/EntityRelationship .

Mặt khác, Riak có công cụ để xây dựng quan hệ. Nó là liên kết. Bạn có thể nhập địa chỉ của tài liệu được liên kết (tại đây nhận xét) vào tài liệu 'gốc' (tài liệu người dùng tại đây). Nó có một mẹo. Nếu nó được phân phối, nó có thể được sửa đổi cùng một lúc ở nhiều địa điểm. Nó sẽ gây ra xung đột và kết quả là cây đồng hồ vectơ rất lớn: / .. không quá tệ, không quá tốt.

Riak cũng có một 'cơ chế' khác. Nó có không gian tên khóa 2 lớp, được gọi là thùng và khóa. Vì vậy, ví dụ sinh viên, Nếu chúng ta có câu lạc bộ A, B và C và sinh viên StudentX, StudentY, bạn có thể duy trì quy ước sau:

{ Key = {ClubA, StudentX}, Value = true }, 
{ Key = {ClubB, StudentX}, Value = true }, 
{ Key = {ClubA, StudentY}, Value = true }

và để đọc mối quan hệ, chỉ cần liệt kê các khóa trong các nhóm nhất định. Có gì sai với điều đó? Thật là chậm chạp. Nhóm niêm yết chưa bao giờ được ưu tiên cho riak. Nó đang trở nên tốt hơn và tốt hơn tho. btw. bạn không lãng phí bộ nhớ vì ví dụ này {true}có thể được liên kết với một hồ sơ đầy đủ của StudentX hoặc Y (ở đây không thể xảy ra xung đột).

Như bạn thấy, NoSQL! = NoSQL. Bạn cần phải xem xét việc thực hiện cụ thể và kiểm tra nó cho chính mình.

Được đề cập trước Cửa hàng cột trông có vẻ phù hợp với các mối quan hệ .. nhưng tất cả phụ thuộc vào nhu cầu A và C và P của bạn;) Nếu bạn không cần A và bạn có ít hơn Peta byte, hãy tiếp tục với MySql hoặc Postgres.

chúc may mắn


1
Riak gần đây đã phát hành v1.0, bổ sung hỗ trợ cho các chỉ mục phụ khi sử dụng phụ trợ LevelDB. Tính năng rất có giá trị.
Jon L.

4
  1. user: userid: comments là một cách tiếp cận hợp lý - hãy nghĩ về nó tương đương với một chỉ mục cột trong SQL, với yêu cầu bổ sung là bạn không thể truy vấn trên các cột không được lập chỉ mục.

  2. Đây là lúc bạn cần suy nghĩ về các yêu cầu của mình. Một danh sách với 30 triệu mục không phải là không hợp lý vì nó chậm, mà vì nó không thực tế để bao giờ làm bất cứ điều gì với nó. Nếu yêu cầu thực sự của bạn là hiển thị một số nhận xét gần đây, bạn nên giữ một danh sách rất ngắn được cập nhật bất cứ khi nào nhận xét được thêm vào - hãy nhớ rằng NoSQL không có yêu cầu chuẩn hóa. Điều kiện cuộc đua là một vấn đề với danh sách trong kho giá trị khóa cơ bản nhưng nhìn chung hoặc nền tảng của bạn hỗ trợ danh sách đúng cách, bạn có thể làm gì đó với khóa hoặc bạn không thực sự quan tâm đến các bản cập nhật không thành công.

  3. Tương tự như đối với nhận xét của người dùng - tạo một từ khóa chỉ mục: bài đăng

  4. Tương tự như vậy - có thể là danh sách các câu lạc bộ như một tài sản của sinh viên và một chỉ mục trên lĩnh vực đó để thu hút tất cả các thành viên của một câu lạc bộ


Vì vậy, về cơ bản mọi thứ chỉ cần danh sách? Có vẻ như cần có một cách tiếp cận phức tạp hơn là chỉ theo dõi các chuỗi id theo cách thủ công. Đối với một, bạn chỉ có thể đi thật xa trước khi chúng trở nên hữu ích. Sau đó, một lần nữa, các dự án hậu-con chính của công nghệ NoSQL (MongoDB, CouchDB, Membase, v.v.) đều là các dự án mới nên có lẽ tôi chỉ cần cho chúng thêm thời gian để tìm ra cách tốt hơn để theo dõi các mối quan hệ.
Xeoncross

Nếu bạn đang sử dụng NoSQL (kho lưu trữ dữ liệu không quan hệ của AKA), bạn cần ngừng suy nghĩ về các thuật ngữ quan hệ. Cách tiếp cận được sử dụng sẽ khác nhau giữa các nền tảng, nhưng ý tưởng cơ bản rằng bạn phải quản lý các chỉ mục là khá phổ biến. Các ví dụ về mối quan hệ bạn đã đưa ra được mô hình hóa theo hai cách khác nhau trong NoSQL: 1) Lưu trữ - không giống như SQL, các cột có thể có nhiều giá trị / phức tạp, vì vậy đối tượng con chỉ là một phần của đối tượng mẹ. 2) Tìm kiếm - Danh sách dài của bạn thực sự là một yêu cầu cho khả năng tìm kiếm, có nghĩa là lập chỉ mục - bạn có thể sử dụng danh sách tùy chỉnh đơn giản hoặc một công cụ tìm kiếm hoàn chỉnh hơn.
Tom Clarkson

2

Bạn có

"user": {
    "userid": "unique value",
    "category": "student",
    "metainfo": "yada yada yada",
    "clubs": ["archery", "kendo"]
}

"comments": {
    "commentid": "unique value",
    "pageid": "unique value",
    "post-time": "ISO Date",
    "userid": "OP id -> THIS IS IMPORTANT"
}

"page": {
    "pageid": "unique value",
    "post-time": "ISO Date",
    "op-id": "user id",
    "tag": ["abc", "zxcv", "qwer"]
}

Trong cơ sở dữ liệu quan hệ, điều bình thường phải làm trong quan hệ một-nhiều là chuẩn hóa dữ liệu. Đó cũng là điều bạn sẽ làm trong cơ sở dữ liệu NoSQL. Chỉ cần lập chỉ mục các trường mà bạn sẽ tìm nạp thông tin.

Ví dụ: các chỉ mục quan trọng đối với bạn là

  • Comment.UserID
  • Nhận xét.PageID
  • Comment.PostTime
  • Trang.Tag []

Nếu bạn đang sử dụng NosDB (Cơ sở dữ liệu NoSQL dựa trên .NET có hỗ trợ SQL) thì các truy vấn của bạn sẽ như thế nào

 SELECT * FROM Comments WHERE userid = That user’;

 SELECT * FROM Comments WHERE pageid = That user’;

 SELECT * FROM Comments WHERE post-time > DateTime('2016, 1, 1');

 SELECT * FROM Page WHERE tag = 'kendo'

Kiểm tra tất cả các loại truy vấn được hỗ trợ từ bảng hoặc tài liệu gian lận SQL của chúng .

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.