디자인 논쟁:버전이 지정된 객체를 저장하고 조작하는 좋은 방법은 무엇입니까?[닫은]

StackOverflow https://stackoverflow.com/questions/11689

문제

나는 의도적으로 이것을 처음에는 아주 모호하게 남겨두고 있습니다.나는 어려운 답변을 찾는 것보다 토론과 어떤 문제가 더 중요한지 찾고 있습니다.

저는 포트폴리오 관리와 같은 기능을 수행하는 앱을 디자인하는 중입니다.지금까지 제가 가지고 있는 디자인은

  • 문제:해결해야 할 문제
  • 해결책:하나 이상의 문제에 대해 제안된 해결책
  • 관계:두 가지 문제, 두 가지 해결책, 또는 문제와 해결책 사이의 관계.더 세분화하면 다음과 같습니다.
    • 부모-자식 - 일종의 분류/트리 계층 구조
    • 중복 - 두 가지 솔루션 또는 두 가지 문제가 실제로 동일한 개념을 다루는 정도
    • 주소 - 문제가 해결책을 해결하는 정도

내 질문은 이러한 것들의 일시적인 성격에 관한 것입니다.문제가 발생했다가 사라집니다.솔루션에는 예상 해결 날짜가 있지만 개발 과정에서 수정될 수 있습니다.문제와 해결책이 발전함에 따라 관계의 정도는 시간이 지남에 따라 변할 수 있습니다.

따라서 질문은 다음과 같습니다.내 포트폴리오의 현재 관점과 과거 관점을 모두 얻을 수 있도록 이러한 버전을 관리하는 가장 좋은 디자인은 무엇입니까?

나중에:@Eric Beard의 답변은 가치가 있지만 아마도 이것을 좀 더 구체적인 질문으로 만들어야 할 것입니다.

나는 세 가지 데이터베이스 디자인을 고려했습니다.각각의 단점을 충분히 보여드리겠습니다.내 질문은 다음과 같습니다무엇을 고를까요, 아니면 더 나은 것을 생각할 수 있나요?

1:문제(및 별도로 솔루션)는 버전 관리에서 자체 참조됩니다.

table problems
  int id | string name | text description | datetime created_at | int previous_version_id

  foreign key previous_version_id -> problems.id

새 버전을 원할 때마다 긴 행을 포함하여 전체 행을 복제해야 하기 때문에 문제가 됩니다. description 열.

2:새 관계 유형을 만듭니다.버전.

table problems
  int id | string name | text description | datetime created_at

이는 단순히 문제 및 해결 방법 테이블의 관계를 관계 테이블로 이동하는 것뿐입니다.동일한 중복 문제이지만 이미 추상적인 관계 개념이 있으므로 약간 "더 깔끔"할 수 있습니다.

삼:보다 Subversion과 유사한 구조를 사용하십시오.모든 문제 및 솔루션 속성을 별도의 테이블로 이동하고 버전을 지정합니다.

table problems
  int id

table attributes
  int id | int thing_id | string thing_type | string name | string value | datetime created_at | int previous_version_id

  foreign key (thing_id, thing_type) -> problems.id or solutions.id
  foreign key previous_version_id -> attributes.id

이는 문제 또는 솔루션의 현재 버전을 로드하려면 속성의 모든 버전을 가져와 날짜별로 정렬한 다음 가장 최신 버전을 사용해야 함을 의미합니다.그것은 끔찍한 일이 아닐 수도 있습니다.나에게 정말 나쁜 점은 데이터베이스에서 이러한 속성을 유형 확인할 수 없다는 것입니다.저것 value 열은 자유 텍스트여야 합니다.나는 만들 수 있다 name 참조 열을 별도의 열로 attribute_names 가 있는 테이블 type 칼럼이지만 그렇지 않습니다. 올바른 유형 attributes 테이블.

나중에 아직도:다중 테이블 외래 키에 대한 @Eric Beard의 의견에 대한 응답:

아쉽게도 제가 설명한 내용은 매우 간단합니다.사물에는 두 가지 유형(문제와 해결책)만 있습니다.실제로 저는 약 9~10가지의 서로 다른 유형의 사물을 갖고 있으므로 귀하의 전략에 따라 9~10개의 외래 키 열이 있게 됩니다.단일 테이블 상속을 사용하고 싶었지만 사물의 공통점이 너무 적어서 극도로 그것들을 하나의 테이블로 합치는 것은 낭비입니다.

도움이 되었습니까?

해결책

흠, 이 사이트랑 좀 비슷한 것 같은데...

데이터베이스 설계에 관한 한 실제로 업데이트를 전혀 수행하지 않고 상황이 변경될 때 버전 번호와 함께 삽입만 하는 SVN과 같은 버전 관리 시스템이 필요할 수 있습니다.이를 MVCC(다중 값 동시성 제어)라고 합니다.위키(wiki)는 이에 대한 또 다른 좋은 예입니다.

다른 팁

@가이우스

foreign key (thing_id, thing_type) -> problems.id or solutions.id

이러한 종류의 "다방향" 외래 키에 주의하세요.내 경험에 따르면 조인할 테이블을 파악하기 전에 조인 조건에서 유형을 확인해야 하면 쿼리 성능이 크게 저하되는 것으로 나타났습니다.우아하지는 않지만 null이 가능한 것 같습니다.

problem_id and solution_id 

훨씬 더 잘 작동할 것입니다.

물론 최신 버전의 레코드를 얻기 위해 검사를 추가해야 하는 경우 MVCC 디자인에서는 쿼리 성능도 저하됩니다.단점은 업데이트 경합에 대해 걱정할 필요가 없다는 것입니다.

이에 대해 어떻게 생각하십니까?

테이블 문제
int id | 문자열 이름 | 텍스트 설명 | dateTime created_at

테이블 문제_개정
int 개정 | int id | 문자열 이름 | 텍스트 설명 | dateTime created_at
외래 키 ID -> Problems.id

업데이트하기 전에 개정 테이블에 추가 삽입을 수행해야 합니다.이 추가 삽입은 빠르지만 이에 대한 비용을 지불해야 합니다.

  1. 현재 버전에 효율적으로 액세스 - 평소대로 문제 선택
  2. 직관적이고 모델링하려는 현실에 가까운 스키마
  3. 스키마의 테이블 간 조인이 효율적으로 유지됩니다.
  4. 비즈니스 트랜잭션당 개정 번호를 사용하면 SVN이 파일에 대해 수행하는 것처럼 테이블 레코드에 대해 버전 관리를 수행할 수 있습니다.

있는 것 같아요

옵션 4:하이브리드

공통 사물 속성을 단일 상속 테이블로 이동한 다음 custom_attributes 테이블.이는 외래 키를 더 단순하게 만들고 중복을 줄이며 유연성을 허용합니다.추가 속성에 대한 유형 안전성 문제는 해결되지 않습니다.또한 이제 사물이 속성을 갖는 두 가지 방법이 있으므로 약간의 복잡성이 추가됩니다.

만약에 description 다른 큰 필드는 Things 테이블에 유지되지만 중복 공간 문제도 해결되지 않습니다.

table things
  int id | int type | string name | text description | datetime created_at | other common fields...
  foreign key type -> thing_types.id

table custom_attributes
  int id | int thing_id | string name | string value
  foreign key thing_id -> things.id

모델에 대해 묻는 일반적인 질문에 쉽게 대답할 수 있는 데이터 구조를 선택하는 것이 좋습니다.대부분의 경우 현재 위치에 관심이 있을 가능성이 가장 높습니다.경우에 따라 특정 문제 및 해결 방법에 대한 기록을 자세히 살펴보고 싶을 수도 있습니다.

현재 위치를 나타내는 문제, 솔루션 및 관계에 대한 테이블이 있을 것입니다.또한 problem_history, solution_history, 등 테이블.이는 문제의 하위 테이블이지만 다음에 대한 추가 열도 포함합니다. VersionNumber 그리고 EffectiveDate.핵심은 (ProblemId, VersionNumber).

문제를 업데이트하면 이전 값을 problem_history 테이블.따라서 특정 시점 쿼리가 가능합니다. problem_history 특정 날짜에 유효한 기록입니다.

이전에 이 작업을 수행한 경우 UNION에 대한 뷰도 만들었습니다. problem 그리고 problem_history 이는 때때로 다양한 쿼리에 유용하기 때문입니다.

옵션 1을 사용하면 모든 과거 데이터가 현재 데이터와 혼합되므로 현재 상황을 쿼리하기가 어렵습니다.

옵션 3은 단순한 쿼리여야 하는 것에 대해 많은 행에 액세스하게 되므로 쿼리 성능이 좋지 않고 코드 작성에도 좋지 않습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top