2011-03-26 9 views
10

나는 언두 - 다시 실행을 허용하기 위해 DB 테이블을 설계하는 방법을 알아 내려고하고있다. 실행 취소 - 다시 실행으로 SQL DB를 설계하는 방법은 무엇입니까?

당신이 작업을 다음과 같은 구조 테이블이 척 :

id <int> 
title <varchar> 
memo <string> 
date_added <datetime> 
date_due <datetime> 

지금 가정을 그 몇 가지 편집이 일어난 며칠 여러 로그 인 이상; 사용자는 버전 중 하나로 돌아가고 싶어합니다.

  1. 는 변경 사항을 추적 별도의 테이블이겠습니까 - 나 - 당신은 (더 나은 용어의 부족 "유령"행)에 작업 테이블에서 변경 내용을 유지하려고 것인가?
  2. 모든 열 또는 매번 변경된 열만 추적 하시겠습니까?

중요한 경우 MySQL을 사용하고 있습니다. 또한, 중요한면, 나는 역사 (ala Photoshop)를 보여주고 사용자가 어떤 버전으로 전환 할 수 있도록하고 싶습니다.

보너스 질문 : 전체 memo 세포를 변경 사항에 저장 하시겠습니까? 아니면 델타 만 저장 하시겠습니까? 이유는 memo 셀이 커질 수 있으며 각 단어가 하나의 단어 또는 문자로 변경 될 수 있기 때문입니다. 델타를 저장하는 것은 파싱을 요구하지만, 언두가 자주 발생하지 않는다면, 처리 시간보다는 공간을 절약하는 것이 더 좋지 않을까요?

도움 주셔서 감사합니다.

+1

비슷한 질문이 여기에 있습니다. 보십시오 [내 대답] (http://stackoverflow.com/questions/5408828/are-there-problems-with-this-soft-delete-solution-using-eav-tables/5410359#5410359) – Ronnis

답변

6

작업 테이블에 대한 기록 테이블을 만들 것입니다. 작업과 구조가 같고 previousId라는 새 필드가 있습니다. 이렇게하면 이전 변경 ID가 유지되므로 다른 변경 사항을 통해 앞뒤로 돌아갈 수 있습니다 (실행 취소/다시 실행).

왜 새로운 기록 테이블입니까? 단순한 이유 때문에 : 작업 테이블에 의도하지 않은 작업을 과부하하지 마십시오.

공간에 대해서는 메모 대신 기록에서 이진 형식을 사용하고 저장할 텍스트의 내용을 압축하십시오. 변경 사항을 감지하려고 시도하지 마십시오. 이 더 나은, 당신은 역사 테이블에 세 개의 열을 유지 할 수 있습니다 : 당신은

최적화 ... 좌절과 시간 낭비가 발생합니다 버그가 코드로 실행됩니다 1. TASKID (작업에 외래 키) 2 data - 바이너리 필드 히스토리 테이블에 저장하기 전에 변경된 필드만을 포함하는 XML 문자열을 작성하십시오.

<task> 
    <title>Title was changed</title> 
    <date_added>2011-03-26 01:29:22<date_added> 
</task> 

이 기본적으로이 시간 당신을 말할 것이다 : 3. previousId 데이터 필드에 대해서는

를,이 같은 XML 문자열을 생성 (변경의 대기열을 유지하고 앞뒤로 탐색 할 수 있도록 도움이 될 것입니다) title과 date_added 필드 만 변경했습니다.

XML 문자열을 만든 후에 원하는 경우 압축하여 기록 테이블의 데이터 필드에 저장하면됩니다.

XML도 유연성을 허용합니다. 작업 테이블에 필드를 추가/제거하면 History 테이블도 업데이트 할 필요가 없습니다. 이렇게하면 작업 테이블과 기록 테이블의 구조가 분리되어 매번 두 개의 테이블을 업데이트 할 필요가 없습니다.

추신 : 일부 인덱스를 추가하여 기록표를 빠르게 탐색 할 수 있습니다. 인덱싱 할 필드 : taskId 및 previousId.이 테이블에 대해 빠른 쿼리가 필요합니다.

희망이 도움이됩니다.

+0

By the 압축을하면 텍스트 크기가 원본 텍스트의 최대 5 %까지 줄어 듭니다. 일반적인 값은 약 10 %이지만 반복적 인 단어가 공통적 인 경우 압축률이 더 높아집니다. – Adi

+0

이것은 영리하지만 "3 필드"아이디어를 잘 모르겠다. 물론 히스토리 테이블의 각 레코드는 자체 ID 필드 (autoincrement), 작업 레코드의 ID에 대한 외부 링크 및 적용 가능한 경우 (즉, 동일한 작업 레코드 ID를 갖는) 이전 히스토리 레코드 ID에 대한 참조를 가져야합니다. 또는 sthg 나는 이해하지 못 했나요? –

+0

@mikerodent 생각이 듭니다. 우리는 작업 테이블 (taskId)과 기록 테이블 (previousId)에 하나씩 변경된 페이로드 (데이터)를 기반으로 히스토리를 탐색 할 수 있도록 2 개의 키가 필요하다고 생각합니다. taskId 및 previousId 필드에 저장되며 변경된 데이터에 액세스하여 필요할 경우 복구 할 수 있습니다. – Adi

4

SQL을 사용하여 비슷한 유형의 작업을 수행 할 때 항상 개정 내역에 두 번째 테이블을 사용합니다. 이렇게하면 기본 테이블이 버전으로 지나치게 커지지 않습니다. 그 이유는 현재의 레코드를 검색하는 것이 시간의 거의 100 %를 차지하고 히스토리를보고 롤백 (실행 취소)하는 일은 매우 드뭅니다.

단일 UNDO 또는 기록 만있는 경우 테이블을 추적하는 것이 좋습니다.

델타 또는 전체 셀을 저장할지 여부는 예상되는 증가/사용량에 따라 다릅니다. 델타를 관리하는 논리를 작성하는 것이 편한 경우 공간을 절약 할 수 있습니다. 일이 실제로 자주 시작하지 않는 새 버전을 만들지 않는다면 (YAGNI 적용)

2

델타 형식으로 리비전을 압축하고 싶지만 빠른 리트리브를 위해 현재 리비젼을 전체적으로 유지해야합니다.

그러나 델타를 기반으로하지 않는 이상 최신 델타로 처리하려면 많은 처리가 필요합니다. 이전 델타로 변경 될 때마다 변경 될 때마다 재 처리가 필요합니다. 따라서 델타는 일반적으로 많은 이점을 얻지 만 복잡성을 증가시키지 않습니다.

마지막으로 내가 저장, 몇 년 전에 MediaWiki, 위키 백과 뒤에 소프트웨어 인 전체 텍스트를 확인하고 공간과 삭제 수정/페이지 전용 테이블 archive을 저장 gzip으로 이전 버전을 압축하기 위해 어떤 수단을 제공했다.

자신의 웹 사이트는 유용 할 수있는 ER diagram of their database layout입니다.