2016-08-01 2 views
1

테이블의 레코드 수준 버전 관리를 위해이 post을 사용하고있었습니다. 나는 아키텍쳐가 히스토리 테이블의 사용을 다룬다는 것을 알아 차렸다. 그러나 내 시나리오에서는 롤백이 필요하지 않지만 시간 기록에서 시점을 검색합니다. 이것은 버전 관리를 위해 하나의 테이블을 사용하는 디자인으로 시도한 곳입니다. 이것은 베어 본 테이블 데이터 (제약 조건, 인덱스 등 없음)입니다. id를 기반으로 인덱스를 작성하려고하는데, 이는 컬럼에 group by 절을 포함하기 때문입니다.기록 테이블이없는 데이터베이스 버전 관리

예를 들어, I는

ID는 식별자 테이블 테스트,

modstamp이 외에도 (null는) 데이터

의 소인이다 가지고 위의 열에는 부기 열이 포함됩니다.

local_modstamp는 레코드

del_modstamp 업데이트되었을 때의 imestamp는 local_modstamp = NULL 레코드의 값을 가질 것 인 기록 백업 중에

가 모든 레코드가 소스로부터 얻어진 삽입 삭제되는 시간 소인 del_stamp = null입니다.

  1. 삽입 : 레코드가 얻어지면

    id |modstamp     |local_modstamp |del_modstamp | 
    ---|---------------------------|---------------|-------------| 
    1 |2016-08-01 15:35:32 +00:00 |    |    | 
    2 |2016-07-29 13:39:45 +00:00 |    |    | 
    3 |2016-07-21 10:15:09 +00:00 |    |    | 
    

    이러한 데이터를 처리하기위한 시나리오 (기준 시간 [ref_time] 가정 프로세스가 실행되는 시간)이다 정상적으로.

  2. 업데이트 : 가장 최근 레코드를 local_modstamp = ref_time으로 업데이트하십시오. 그런 다음 새 레코드를 삽입하십시오. 쿼리는 다음과 같습니다 갱신 테스트 세트 local_modstamp = ID = 및 local_modstamp가 null는 아니고, del_modstamp이

  3. 삭제 테스트 값 (...)에 널 (null) 삽입되지이다 : del_modstamp와 가장 최근의 기록을 갱신 = ref_time. 업데이트 테스트 = 경우 ID를 del_modstamp 설정 = 및 local_modstamp는 null가 아니고, del_modstamp이

디자인은 local_modstamp가 null는 아니고, del_modstamp가 null가 아닌 최신 기록을 얻는 것을 목적으로 널 (null)이 아닙니다.

select id, max(modstamp) from test where modstamp <= <ref_time> and (del_modstamp is null || del_modstamp <= <ref_time>) group by id; 

내가 null를 사용하는 실수 (? 내가 가진)을 만든 것 같다 : 그러나, 나는 쿼리를 사용하여 시간에 지점을 검색하려는 문제 (가장 안쪽 쿼리)에 달렸다 테이블의 최신 레코드를 식별하는 자리 표시 자입니다. 기존 설계를 사용하여 시점 기록을 얻는 방법이 있습니까?

그렇지 않으면 가능한 해결책은 local_modstamp를 최신 레코드로 설정하는 것입니다. 이것은 업데이트의 경우 max (local_modstamp)를 사용하여 로직을 업데이트해야합니다. 특정 시점 데이터를 가져 오기 위해 기존 아키텍처를 유지할 수 있습니까?

현재 SQL Server를 사용하고 있지만이 디자인은 다른 데이터베이스 제품에도 적용될 수 있습니다. 벤더 특정 hacks을 사용하는 대신 데이터를 검색하는 좀 더 일반적인 방법을 사용하려고합니다.

답변

1

버전 표준 양식 소개. 이 테이블을 고려해

create table Entities(
    ID  int identity primary key, 
    S1  [type], -- Static data 
    Sn  [type], -- more static data 
    V1  [type], -- Volatile data 
    Vn  [type] -- more volatile data 
); 

정적 데이터는 기업의 수명 기간 동안 변경되지 않습니다 또는 추적을 필요로하지 않는 데이터입니다. 휘발성 데이터 변경 및 이러한 변경 사항을 추적해야합니다. 별도의 테이블에

이동 휘발성 특성 :

create table EntityVersions(
    ID  int not null, 
    Effective date not null default sysdate(), 
    Deleted bit not null default 0, 
    V1  [type], 
    Vn  [type], 
    constraint PK_EntityVersions primary key(ID, Effective), 
    constraint FK_EntityVersionEntity foreign key(ID) 
     references Entities(ID) 
); 

엔티티 테이블이 더 이상 휘발성 속성이 포함되어 있습니다.

삽입 작업은 정적 데이터가있는 마스터 엔터티 레코드를 만들어 고유 한 ID 값을 생성합니다. 이 값은 첫 번째 버전을 휘발성 데이터의 초기 값과 함께 삽입하는 데 사용됩니다. 일반적으로 업데이트는 정적 값이 실제로 변경되지 않는 한 마스터 테이블에 아무 것도 수행하지 않으며 새 버전의 새로운 휘발성 데이터가 버전 테이블에 기록됩니다. 기존 버전, 특히 최신 또는 "현재"버전은 변경되지 않습니다. 새 버전이 삽입되어 작업이 종료됩니다.

최신 버전 또는 모든 버전을 "실행 취소"하려면 실제로 버전 표에서 해당 버전을 삭제하십시오. 예를 들어

, 다음과 같은 속성을 가진 직원 테이블 :

EmployeeNum, HireDate, FirstName, LastName, PayRate, Dept, PhoneExt 

EmployeeNum은 물론, HIREDATE 및 FIRSTNAME과 함께 정적이 될 것입니다. PhoneExt는 수시로 변경 될 수 있지만 Google은 상관하지 않습니다. 따라서 정적으로 지정됩니다. 최종 디자인 :

Employees_S 
=========== 
    EmployeeNum (PK), HireDate, FirstName, PhoneExt 

Employees_V 
=========== 
    EmployeeNum (PK), Effective (PK), IsDeleted, LastName, PayRate, Dept 

2016 년 1 월 1 일 우리는 샐리 스미스를 고용했습니다. 정적 데이터는 Employees_S에 삽입되어 EmployeeNum 값 1001을 생성합니다.이 값을 사용하여 첫 번째 버전을 삽입합니다.

3월 1일에
Employees_S 
=========== 
    1001, 2016-01-01, Sally, 12345 

Employees_V 
=========== 
    1001, 2016-01-01, 0, Smith, 35.00, Eng 

, 그녀는 임금 인상 얻는다 : 1 일에

Employees_S 
=========== 
    1001, 2016-01-01, Sally, 12345 

Employees_V 
=========== 
    1001, 2016-01-01, 0, Smith, 35.00, Eng 
    1001, 2016-03-01, 0, Smith, 40.00, Eng 

을, 그녀는 결혼하기 :

Employees_S 
=========== 
    1001, 2016-01-01, Sally, 12345 

Employees_V 
=========== 
    1001, 2016-01-01, 0, Smith, 35.00, Eng 
    1001, 2016-03-01, 0, Smith, 40.00, Eng 
    1001, 2016-05-01, 0, Jones, 40.00, Eng 

주 그 이외의 동일한 개체의 버전, 유효 일자가 동일 할 수 없다는 제한은 서로 완전히 독립적입니다.

select s.EmployeeNum, s.HireDate, s.FirstName, v.LastName, v.PayRate, v.Dept, s.PhoneExt 
from Employees_S s 
join Employees_V v 
    on v.EmployeeNum = s.EmployeeNum 
    and v.Effective = (select Max(Effective) 
         from Employees_V 
         where EmployeeNum = v.EmployeeNum 
          and Effective <= SysDate()) 
where s.EmployeeNum = 1001 
    and v.IsDeleted = 0; 

여기에 멋진 부분 :

직원 1001의 현재 상태가 여기처럼 보이는 쿼리입니다 무엇을 참조하십시오. - 서브 쿼리의 마지막 줄을 제외하고

select s.EmployeeNum, s.HireDate, s.FirstName, v.LastName, v.PayRate, v.Dept, s.PhoneExt 
from Employees_S s 
join Employees_V v 
    on v.EmployeeNum = s.EmployeeNum 
    and v.Effective = (select Max(Effective) 
         from Employees_V 
         where EmployeeNum = v.EmployeeNum 
          and Effective <= '2016-02-11') 
where s.EmployeeNum = 1001 
    and v.IsDeleted = 0; 

그것은 동일한 쿼리입니다 : 직원 1001의 상태가 어떻게 생겼는지 확인하려면 말을 2월 11일, 여기에 쿼리입니다. 현재 및 실행 기록 데이터는 동일한 테이블에 있으며 동일한 명령문으로 조회됩니다.

다음은 멋진 기능입니다. 7 월 1 일이며, 9 월 1 일에 Sally가 마케팅 부서로 이전 할 예정이며 또 다른 임금 인상이 있습니다. 문서 작업은 이미 완료되었습니다. 가서 새로운 데이터를 삽입 : 다음 - 투 - 마지막 버전은 여전히 ​​현재 버전하지만 9월는 마케팅 데이터가 표시됩니다 1 일 이후 실행되는 첫 번째 쿼리로 표시됩니다

Employees_S 
=========== 
    1001, 2016-01-01, Sally, 12345 

Employees_V 
=========== 
    1001, 2016-01-01, 0, Smith, 35.00, Eng 
    1001, 2016-03-01, 0, Smith, 40.00, Eng 
    1001, 2016-05-01, 0, Jones, 40.00, Eng 
    1001, 2016-09-01, 0, Jones, 50.00, Mkt 

.

Here은 기술 박람회에서 몇 번이나 발표 한 프레젠테이션의 슬라이드입니다. 여기에는 쿼리를 포함하여 위의 모든 작업을 수행하는 방법에 대한 세부 정보가 포함되어 있습니다. 그리고 here은 훨씬 더 자세하게 설명하는 문서입니다.

+0

삭제를 수행하면 최신 버전이 1로 표시 되나요? 아니면 삽입되고 1로 삭제 표시됩니까? 이것은 쿼리의'및 v.IsDeleted = 0;'쿼리에 영향을줍니다. 예를 들어 Sally는 2016-10-01에 회사를 남겨 둡니다.하지만 2016-06-01에있는 상태를 쿼리해야하며, 목적을 달성하는 절에서 isDeleted를 무시할 것입니까? 나는 표를 정상화할지의 수수께끼에 처해있다. 나는 스키마에서 수천 정도를 백업하고 테이블을 두 개로 정규화해도 테이블은 부 풀릴 수 없다. 동일한 테이블에서이 작업을 이식 할 수 있습니까? – dmachop

+0

정적 데이터가없고 모든 열이 버전 테이블에 버전 관리되는 경우 위의 해결 방법은 단일 테이블로 수행 할 수 있습니다. 특정 시점 또는 최신 데이터를 선택할 때마다 임시 테이블 (버전에서 고유 한 ID 선택)을 생성 한 다음 필요에 따라 조인을 수행해야합니다. – dmachop

+0

PK는 정적이며 경험상 다른 정적 속성은 거의 없음을 보여줍니다. 그러나 마스터 테이블에 PK 만있는 경우에도 여전히 두 개의 테이블이 필요합니다. 다른 테이블의 FK 대상이 되려면 버전없는 마스터 테이블이 필요합니다. 다른 버전 관리 체계를 읽었을 때 극도로 극복 할 수없는 문제는 항상 참조 무결성의 부족이었습니다. 이 (vnf)는이 문제를 해결합니다. – TommCatt

관련 문제