NoSQL에서 레코드 관계를 어떻게 추적합니까?


117

NoSQL KVP 또는 문서 데이터베이스에서 외래 키 및 인덱스에 해당하는 것을 파악하려고합니다. (두 개체 간의 관계를 표시하는 키를 추가하는) 중추 테이블이 없기 때문에 일반 웹 페이지에 유용한 방식으로 데이터를 검색 할 수있는 방법에 대해 정말 당황합니다.

사용자가 있는데이 사용자는 사이트 전체에 많은 댓글을 남깁니다. 사용자 댓글을 추적 할 수있는 유일한 방법은

  1. 사용자 개체에 포함 (매우 쓸모없는 것 같음)
  2. user_id:comments필요에 따라 가져올 수 있도록 각 주석의 키 [comment : 34, comment : 197 등 ...] 목록을 포함 하는 값을 만들고 유지 합니다.

그러나 두 번째 예를 살펴보면 3 천만 개의 ID가 포함될 수있는 "active_comments"라는 키와 같은 다른 항목을 추적하는 데 사용할 때 곧 벽돌 벽에 부딪 히게되므로 최근 몇 가지를 알기 위해 각 페이지를 쿼리 하는 데 TON 이 필요합니다. 활성 댓글. 또한 많은 페이지에서 동시에 업데이트를 시도 할 수 있으므로 경쟁 조건에 매우 취약합니다 .

NoSQL 데이터베이스에서 다음과 같은 관계를 어떻게 추적 할 수 있습니까?

  • 사용자의 모든 댓글
  • 모든 활성 댓글
  • [키워드] 태그가 지정된 모든 게시물
  • 클럽의 모든 학생 또는 학생이 속한 모든 클럽

아니면 이것에 대해 잘못 생각하고 있습니까?


NoSQL 데이터베이스에서는이를 수행하는 한 가지 방법이 없습니다.이 질문은 C 프로그램에서 관계를 추적하는 방법을 묻는 것과 다소 비슷합니다.
stonemetal 2010

3
와우, RDBMS를 대체하는 NoSQL에 대한 과대 광고는 불가능하다고 생각합니다.
Xeoncross 2010

11
예, NoSQL은 확실히 과장되었습니다. 새로운 기술이 적절한 상황에서 유용하지 않다고 말하는 것은 아니지만 RDBMS를 대체 ​​할 것이라고 생각하는 것은 어리석은 일입니다. en.wikipedia.org/wiki/Hype_cycle
Bill Karwin 2010

1
'사용자'모음과 댓글 모음 만 갖고 있지 않겠습니까? 그런 다음 각 주석은 값이 사용자 ID에 대한 참조 인 '작성자'속성과 동일합니까?
CodeFinity 2019-04-12

답변:


186

"NoSQL 방식"으로 다 대다 연결을 저장하는 방법에 대한 모든 답변은 데이터를 중복 저장 하는 것과 같은 방식으로 축소됩니다 .

NoSQL에서는 데이터 엔터티 간의 관계를 기반으로 데이터베이스를 디자인하지 않습니다. 데이터베이스에 대해 실행할 쿼리를 기반으로 데이터베이스를 디자인합니다. 관계형 데이터베이스를 비정규 화하는 데 사용하는 것과 동일한 기준을 사용하십시오. 데이터가 응집력을 갖는 것이 더 중요하다면 (정규화 된 테이블 대신 쉼표로 구분 된 목록의 값을 생각해보십시오) 그렇게하십시오.

그러나 이것은 필연적으로 다른 유형의 쿼리 (주어진 사용자의 모든 기사에 대한 주석)를 희생시키면서 한 유형의 쿼리 (예 : 특정 기사에 대한 사용자의 댓글)에 대해 최적화됩니다. 애플리케이션에서 두 가지 유형의 쿼리를 동일하게 최적화해야하는 경우 비정규 화해서는 안됩니다. 마찬가지로 데이터를 관계형 방식으로 사용해야하는 경우 NoSQL 솔루션을 사용해서는 안됩니다.

비정규 화 및 중복으로 인해 중복 된 데이터 세트가 서로 동기화되지 않을 위험이 있습니다. 이것을 이상 이라고합니다 . 정규화 된 관계형 데이터베이스를 사용할 때 RDBMS는 이상을 방지 할 수 있습니다. 비정규 화 된 데이터베이스 또는 NoSQL에서는 이상을 방지하기 위해 애플리케이션 코드를 작성하는 것이 귀하의 책임이됩니다.

NoSQL 데이터베이스가 이상을 방지하기 위해 열심히 일하는 것이 좋다고 생각할 수도 있습니다. 이를 수행 할 수있는 패러다임이 있습니다. 관계형 패러다임입니다.


20
"관계형 방식으로 데이터를 사용해야하는 경우 NoSQL 솔루션을 사용해서는 안됩니다."-NoSQL을 실행하는 다른 사람들은 어떻게이 솔루션을 사용하지 않을까요? 애플리케이션을 처음 설계 할 때 데이터를 쿼리 할 모든 방법을 어떻게 알 수 있습니까? 폭스 예를 들어, 나는 등 스팸으로 표시 최근 댓글, 사용자가 댓글, 태그에 의해 설명, 특정 게시물에 대한 의견, 의견, 활동적인 의견, 가장 높은 평가 의견, 할 수 있습니다
Xeoncross

14
정확합니다. NoSQL의 옹호자들이 주장하는 것처럼 "그냥 작동합니다"와 같은 것은 없습니다. 관계형 데이터 모델링을 위해 사전에 여러 분석을 수행하거나, 최우선 순위 쿼리에 대해 사전에 여러 분석을 수행하거나, 디자인의 어느 부분을 발견 할 때 프로젝트 전체에서 많은 비용이 드는 리팩토링을 수행합니다. 사전에 충분한 분석을 얻지 못했습니다.
Bill Karwin 2010

1
데이터를 중복 저장하는 경우 어떻게 업데이트해야합니까? 예를 들어, 이름을 변경하고 몇 가지 의견을 썼습니다. 그의 이름은 이미 사용자 컬렉션에서 변경되었지만 주석 컬렉션에서 중복 저장된 모든 이름을 변경하는 방법은 무엇입니까?
Mohammad Kermani

3
@ M98, 아,이 전략에서 약점을 발견했습니다. 업데이트해야하는 모든 위치에 대해 알고 있어야하며, 업데이트 할 때 모두 업데이트하는 코드를 애플리케이션에 작성해야합니다. 행운을 빕니다!
Bill Karwin

2
비정규 화 된 관계형 데이터베이스 에도 동일한 문제가 존재 합니다.
Bill Karwin

5

couchDB 접근 방식은 맵 단계에서 적절한 클래스를 내보내고이를 reduce로 요약 할 것을 제안합니다. 따라서 모든 주석을 매핑 1하고 주어진 사용자에 대해 방출 하고 나중에 하나만 출력 할 수 있습니다. 그러나 couchDB에서 추적 가능한 모든 데이터의 영구 뷰를 구축하려면 많은 디스크 스토리지가 필요합니다. btw 그들은 또한 관계에 대한이 위키 페이지를 가지고 있습니다 : http://wiki.apache.org/couchdb/EntityRelationship .

반면에 Riak은 관계를 구축하는 도구를 가지고 있습니다. 링크입니다. '루트'문서 (여기서는 사용자 문서)에 링크 된 (여기 주석) 문서의 주소를 입력 할 수 있습니다. 하나의 트릭이 있습니다. 배포 된 경우 여러 위치에서 한 번에 수정 될 수 있습니다. 그것은 충돌을 일으켜 결과적으로 거대한 벡터 클록 트리를 유발합니다 : / .. 그렇게 나쁘지 않고 좋지 않습니다.

Riak은 또 다른 '메커니즘'을 가지고 있습니다. 버킷 및 키라고하는 2 계층 키 네임 스페이스가 있습니다. 따라서 학생의 예를 들어, 클럽 A, B 및 C와 학생 StudentX, StudentY가있는 경우 다음 대회를 유지할 수 있습니다.

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

관계를 읽으려면 주어진 버킷의 키를 나열하십시오. 그게 무슨 문제입니까? 젠장 느리다. riak에게는 버킷 나열이 우선 순위가 아니 었습니다. 점점 더 좋아지고 있습니다. btw. 이 예제 {true}는 StudentX 또는 Y의 단일 전체 프로필에 연결될 수 있기 때문에 메모리를 낭비하지 않습니다 (여기서 충돌은 가능하지 않음).

보시다시피 NoSQL! = NoSQL. 특정 구현을 살펴보고 직접 테스트해야합니다.

Column store가 관계에 잘 어울리는 것처럼 보이기 전에 언급했지만 A와 C 및 P 요구 사항에 따라 다릅니다.) A가 필요하지 않고 Peta 바이트보다 적 으면 그대로 두십시오. MySql 또는 Postgres를 사용하십시오.

행운을 빕니다


1
Riak은 최근 LevelDB 백엔드를 사용할 때 보조 인덱스에 대한 지원을 추가하는 v1.0을 출시했습니다. 매우 귀중한 기능입니다.
Jon L.

4
  1. user : userid : comments는 합리적인 접근 방식입니다. 인덱싱되지 않은 열에 대해 쿼리 할 수 ​​없다는 요구 사항이 추가 된 SQL의 열 인덱스와 동일하다고 생각하십시오.

  2. 여기에서 요구 사항에 대해 생각해야합니다. 3 천만 개의 항목이있는 목록은 속도가 느리기 때문에 불합리한 것이 아니라 어떤 작업도 수행하는 것이 비현실적이기 때문입니다. 실제 요구 사항이 최근 주석을 표시하는 것이라면 주석이 추가 될 때마다 업데이트되는 매우 짧은 목록을 유지하는 것이 좋습니다. NoSQL에는 정규화 요구 사항이 없습니다. 경쟁 조건은 기본 키 값 저장소에있는 목록의 문제이지만 일반적으로 플랫폼이 목록을 올바르게 지원하거나 잠금으로 작업을 수행 할 수 있거나 실제로 실패한 업데이트에 대해 신경 쓰지 않습니다.

  3. 사용자 댓글과 동일-색인 키워드를 만듭니다.

  4. 더 많은 것-아마도 학생의 재산으로 클럽 목록과 클럽의 모든 회원을 얻기위한 해당 분야의 색인


그래서 기본적으로 모든 것이 목록 만 필요합니까? ID 문자열을 수동으로 추적하는 것보다 더 정교한 접근 방식이 있어야 할 것 같습니다. 우선, 유용하기 위해 커지기 전에 지금까지만 갈 수 있습니다. 다시 말하지만, NoSQL 기술의 주요 포스터 자식 프로젝트 (MongoDB, CouchDB, Membase 등)는 모두 새로운 프로젝트이므로 관계를 추적하는 더 나은 방법을 찾기 위해 더 많은 시간을 주면됩니다.
Xeoncross 2010

NoSQL (일명 비 관계형 데이터 저장소)을 사용하는 경우 관계형 용어에 대한 생각을 중단해야합니다. 사용되는 접근 방식은 플랫폼마다 다르지만 인덱스를 관리해야한다는 기본 개념은 상당히 보편적입니다. 제공 한 관계 예제는 NoSQL에서 두 가지 다른 방식으로 모델링됩니다. 1) 스토리지-SQL과 달리 열은 다중 / 복잡한 값을 가질 수 있으므로 자식 개체는 부모 개체의 일부일뿐입니다. 2) 검색-긴 목록은 실제로 검색 가능성에 대한 요구 사항입니다. 즉, 인덱싱을 의미합니다. 간단한 사용자 지정 목록이나보다 완전한 검색 엔진을 사용할 수 있습니다.
Tom Clarkson

2

당신은

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

관계형 데이터베이스에서 정상적인 일대 다 관계는 데이터를 정규화하는 것입니다. 이것은 NoSQL 데이터베이스에서도 똑같은 일입니다. 정보를 가져올 필드를 간단히 색인화하십시오.

예를 들어 중요한 색인은 다음과 같습니다.

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

당신이 사용하는 경우 NosDB (SQL 지원하는 .NET 기반 형 NoSQL 데이터베이스) 쿼리처럼 될 것입니다

 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'

SQL 치트 시트 또는 문서 에서 지원되는 모든 쿼리 유형을 확인하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.