2010-11-08 38 views
84

Tôi đang cố gắng tìm ra tương đương với các khóa và chỉ mục ngoại trong cơ sở dữ liệu NoSQL KVP hoặc Tài liệu. Vì không có bảng quan trọng (để thêm các khóa đánh dấu mối quan hệ giữa hai đối tượng), 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 có ích cho các trang web thông thường.Làm thế nào để bạn theo dõi các mối quan hệ kỷ lục trong NoSQL?

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

  1. Nhúng chúng vào đối tượng người dùng (mà có vẻ khá vô dụng)
  2. Tạo và duy trì một giá trị user_id:comments có chứa một danh sách của mỗi bình luận của key [comment: 34, comment: 197, etc ...] để tôi có thể lấy chúng khi cần thiết.

Tuy nhiên, lấy ví dụ thứ hai bạn sẽ sớm đạt mức bức tường gạch khi bạn sử dụng nó để theo dõi những thứ khác như một chìa khóa gọi là "active_comments" mà có thể chứa 30 triệu id trong nó làm cho nó chi phí một TÔN để truy vấn mỗi trang chỉ để biết một số nhận xét đang hoạt động gần đây. Nó cũng sẽ rất dễ bị điều kiện chủng tộc vì nhiều trang có thể cố cập nhật cùng một lúc.

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

  • Tất cả các ý kiến ​​của người dùng
  • Tất cả các ý kiến ​​tích cực
  • Tất cả bài viết được gắn thẻ với [từ khoá]
  • 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ộ học sinh đang

Hay tôi đang nghĩ về điều này không chính xác?

+0

Không có cách nào để làm điều đó trong cơ sở dữ liệu NoSQL, câu hỏi này đúng hơn là một thân nhân để hỏi làm cách nào tôi 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 hype về NoSQL thay thế RDBMS là không thể. – Xeoncross

+10

Vâng, NoSQL chắc chắn là overhyped. Tôi không nói rằng các công nghệ mới không hữu ích trong hoàn cảnh thích hợp, nhưng thật vô lý khi nghĩ rằng họ sẽ thay thế RDBMS. Xem http://en.wikipedia.org/wiki/Hype_cycle –

Trả lời

124

Tất cả các câu trả lời về cách thức để lưu trữ nhiều-nhiều hiệp hội trong "NoSQL cách" giảm để điều tương tự: dữ liệu lưu trữ 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 bạn dựa trên các truy vấn bạn sẽ chạy với nó. Sử dụng cùng tiêu chí bạn sẽ sử dụng để chuẩn hóa một cơ sở dữ liệu quan hệ: nếu nó quan trọng hơn đối với dữ liệu để có sự gắn kết (suy nghĩ về các giá trị trong danh sách được phân cách bằng dấu phẩy thay vì bảng được 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 viết nhất định) về chi phí của các loại truy vấn khác (bình luận 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 cho cả hai loại truy vấn được tối ưu hóa như nhau, bạn không nên không chuẩn hóa. 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ó rủi ro với việc không chuẩn hóa và dự phòng mà các tập dữ liệu dự phòng sẽ không đồng bộ với nhau. Điều này được gọi là bất thường bất thường. Khi bạn sử dụng một cơ sở dữ liệu quan hệ chuẩn hóa, RDBMS có thể ngăn chặn các bất thường. Trong một cơ sở dữ liệu không chuẩn hóa hoặc trong NoSQL, nó trở thành trách nhiệm của bạn trong việc viết mã ứng dụng để ngăn chặn các bất thường.

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

+11

"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 cách nào để những người khác chạy NoSQL thoát khỏi nó? Làm cách 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 bạn thiết kế ứng dụng lần đầu tiên? Ví dụ Fox, tôi có thể muốn nhận xét gần đây, nhận xét của người dùng, nhận xét theo thẻ, nhận xét cho bài đăng cụ thể, nhận xét đánh dấu là spam, nhận xét đang hoạt động, nhận xét được đánh giá cao nhất, v.v. – Xeoncross

+7

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

+0

@Xeoncross Tôi cũng hiểu vấn đề này. Có một cái nhìn vào chỉ số phụ. Nói chung, NoSQL tạo ra các chỉ mục phụ để đáp ứng các trường hợp sử dụng kinh doanh khác nhau. Mặc dù số lượng chỉ mục phụ thấp hơn được ưu tiên hơn. –

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

  2. Đây là nơi 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, nhưng bởi vì nó không thực tế để 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 một bình luận đượ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 chủng tộc là vấn đề với danh sách trong kho khóa giá trị cơ bản nhưng nói chung nền tảng của bạn hỗ trợ danh sách đúng cách, bạn có thể làm điều gì đó với khóa hoặc bạn không thực sự quan tâm đến cập nhật không thành công.

  3. Tương tự như đối với người dùng bình luận - tạo ra một từ khóa chỉ mục: bài viết

  4. More cùng - có thể là một 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 đó để có được tất cả các thành viên của câu lạc bộ

+0

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

+0

Nếu bạn đang sử dụng NoSQL (các kho dữ liệu phi quan hệ AKA), bạn cần phải ngừng suy nghĩ trong 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 mà bạn phải quản lý các chỉ mục là khá phổ biến. Ví dụ về mối quan hệ bạn đã đưa ra được mô hình 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 cha. 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 công cụ tìm kiếm hoàn chỉnh hơn. –

3

cách tiếp cận CouchDB đề nghị để phát ra các lớp học phù hợp của nội dung trong giai đoạn bản đồ và tóm tắt nó trong giảm .. vì vậy, bạn có thể lập bản đồ tất cả các ý kiến ​​và phát ra 1 cho người sử dụng nhất định và sau đó in ra chỉ những người thân.Nó sẽ yêu cầu tuy nhiên rất nhiều dung lượng lưu trữ đĩa để xây dựng các khung nhìn liên tục của tất cả cá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.

Riak mặt khác có công cụ để xây dựng mối quan hệ. Đó là liên kết. Bạn có thể nhập địa chỉ của tài liệu được liên kết (ở đây nhận xét) vào tài liệu 'root' (tài liệu người dùng ở đây). Nó có một thủ thuật. 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ơ lớn:/..không tệ lắm, không tốt lắm.

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à bucket và key. 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ì sau ước:

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

và đọc liên quan chỉ phím danh sách trong xô nhất định. Có gì sai với điều đó? Nó rất chậm. Danh sách nhóm không bao giờ được ưu tiên cho riak. Nó đang nhận được tho tốt hơn và tốt hơn. 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 xung đột được).

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

Được đề cập trước khi các cửa hàng cột trông phù hợp cho 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 chỉ cần rời khỏi nó, hãy tiếp tục MySql hoặc Postgres.

may mắn

+1

Riak gần đây đã phát hành phiên bản 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ị. –

0

Tôi nghĩ RavenDB cung cấp giải pháp tốt cho vấn đề này với Lập chỉ mục. Thông tin trên trang chính http://ravendb.net/ giải thích khái niệm đủ tốt để bạn có thể tạo ra một cái gì đó tương tự cho công nghệ của bạn.

1

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"] 
} 

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

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

  • Comment.UserID
  • Comment.PageID
  • Comment.PostTime
  • Page.Tag []

Nếu bạn đang sử dụng NosDB (A .NET based NoSQL Database with SQL support) truy vấn của bạn sẽ giống như

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ừ tài liệu SQL cheat sheet hoặc tài liệu của chúng.

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