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

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

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

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

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

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

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

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



답변

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

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

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

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

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


답변

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

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

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

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


답변

당신은

"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 치트 시트 또는 문서 에서 지원되는 모든 쿼리 유형을 확인하십시오 .


답변