- 이하는 물리설계 전 업무분석 및 현업화의 회의를 통해 도출해야 하는 내용들이다.
-
경고
-
어플리케이션을 반드시 고려해서 설계를 진행해야 한다.
- PK는 단순히 DB상에서의 의미만이 아니다. 어플리케이션의 Map이나 List의 index 및 복합키 객체를 고려해야 한다.
- DB컬럼터입, 관계정의, 정규화 등은 모두 Class 기준으로 생성하는게 무난하다.
-
코드성 데이터 파악 및 이력/상속/identity/캐싱 등을 미리 고려하여 설계해야 한다.
- 이들은 DB만을 봤을때 크게 고려하지 않아도 되지만 어플리케이션과는 밀접한 관계가 있다.
-
-
Entity 타입과 Value타입의 구분
- 일반적으로 RDB에서 지원하는 타입(VChar, CLob 등)이 Vaue타입이며 Entity타입은 테이블이 된다.
-
하지만 ORM의 도움으로 이러한 관계를 적절히 조절 / 매핑할 수 있다. (DB만 잘 알아는것 가지고는 DB설계를 잘할 수 없다!)
- 예를 들자면 컴포지션 타입이 있다. 이는 DB전문가가 생각해 낼 수 없는 영역이다.
-
디자인 패턴
-
롤 모델 (Pair키)
- 기업 + 롤을 identity하게 연결해서 거래처 라는 롤 모델을 만든다.
- 기업은 고객/구매자 라는 2가지 룰을 가지며 고로 거래처는 2가지 형태가 나온다.
- 롤은 방대하고 갱신 가능할때만 DB에서 관리한다.
- 명시적인 pair키를 가지기 때문에 자료를 분명하게 나타낼수는 있지만 어플에서 관리하기가 짜증난다.
-
거래 모델
- 위의 롤 모델인 거래처를 non-Identity하게 2개 묶어서 "거래"를 만든다.
- 이는 N:N매핑에서 브릿지 역활을 한다.
-
-
키 설정
-
특별한 이유가 없다면 인조키 사용을 강력하게 권장한다.
- We recommend that identifiers be 'synthetic', that is, generated with no business meaning. (자세한 내용은 Hibernate-ORM 분서 참조)
-
경험상 자연키는 항상 말썽을 일으킨다.
- 자연키는 유지보수와 스키마 개선이 훨씬 힘들다.
- PK는 바뀔수 있는것이 되면 골치아파진다. SID같은걸 PK로 두지 말자.. 가상키가 많이 사용되는 이유중 하나이다.
- 가상키는 만병통치약이 아니다.. 하지만 효과는 탁월하다.
-
인조키다 유리할때는?
- 후보키(PK의 개념)가 너무 많을때, 후보키가 없거나 있더라도 확장성을 고려할 때.
- 후보키의 길이가 클때, 후보키가 너무 많은 수의 애트리뷰트들과 관계를 맺을 때.
- Hibernate등을 사용할때.
-
인조키의 단점은?
- 자연키는 그 자체로도 강력한 무결성을 보장한다. 하지만 인조키는 이들 키값들이 중복되어도 오류를 내지 않고 insert된다.
- 그러나 이 인조키는 Unique한 속성을 보장해주지 못함으로 나머지 대리키들에 유니크 인덱스를 주어 사실상의 키 기능을 하게 한다.
- 원래 개념상에서 PK와 UID(Unique ID)는 다른 개념이다. 하지만 개념만 다를뿐 실제는 같기 때문에 현업의 ERD에서(ER-Win 등의 툴 포함) UID를 PK로 표기한다.
-
-
정규화 어느것이효율적?
-
java객체가 필요한 만큼만 정규화하라. 자동으로 정규화가 될것이다.
-
가볍고 많은 row 보다 무겁고 적은 row가 훨씬 다루기 쉽다.(좋은건 아니다.) 명심할것!
-
정규형에 해당되지 않는 "계산된 값"등은 추가하지 말것!
-
통계형 컬럼은 특이한 경우(계산에 시간이 오래 걸림)를 제외하면 생성하지 않는다. 실시간 계산한다.
- ex) 자식 컬럼들의 합계 컬럼
- ex) 차액(A컬럼-B컬럼 하면 단순 계산되어지는) 컬럼 등
- "넣을땐 힘들어도 뺄때는 편하다." 라는건 나중에 생각해도 늦지않다. (이는 다분히 SQL중심적인 사고이다. 과연 편할까?)
-
-
이력 테이블 설정
-
반드시 현업과 상의 및 증거를 남길것!
- 이력 테이블 , 기간과 데이터 범위도 포함
-
이력의 의도 파악
- 이력 내용을 조회가 가능해야 한지?
- 특점 이력시점으로 롤백이 가능해야 하는지?
-
이력 유형
-
스냅샷 방식 (Backup테이블 방식)
-
변경된 데이터가 비지니스 로직에 사용되지 않을때 사용.
- 웬만하면 무조건 이방법을 사용할것!!
- 기존 로직에서 간단히 백업로직 추가 가능 (날자 , 일련번호 등 추가)
- 장점 : 다른 기능을 손볼 필요 없이 생성 가능 , 예정에 없었지만 이력을 남겨야 할때 유용. 대량의 데이터에 유용.
-
단점 : 기존 기능과는 연계성이 떨어짐. 이력을 볼려면 별도의 API를 구축해야함.
- ex) 이력서 제출시 개인정보를 함께 제출한다. 도중에 개인정보가 변경등록했음에도 불구하고
이력서를 읽으면 예전의 개인정보가 나타나야하는 경우. 이러한 경우는 사용할 수 없다.
- ex) 이력서 제출시 개인정보를 함께 제출한다. 도중에 개인정보가 변경등록했음에도 불구하고
-
스냅샷 종류
- 데이터 전체를 전부 복사 (이게 일반적)
- 컬럼마다 테이블을 만들어서 변경시 복사
- 하나의 컬럼에 String 방식으로 변경분을 나열해서 기재.
-
-
상태 코드 방식
- 변경된 데이터가 비지니스 로직에 사용됨.
- 일반적인 방법으로 삭제 or 변경시 delete가 아닌 state를 변경
- 수정 이력의 필요시 상위Key를 생성해서 변경 이전과의 관계를 유지함. (A -> B로 수정됨을 알림)
- 장점 : 복잡하지만 변경된 객체(과거이력)도 여전히 기존 로직API로 참조 가능.
- 단점 : select 등의 모든 로직에 추가 where 조건이 들어가야 함. 실수 유발 가능.
-
문자열 방식
- 이력시 이력 실적테이블에 물질정보가 들어가야 한다면 -> 물질정보의 PK를 가지는 대신 물질정보 자체의 정보를 복사 / 입력한다.
- 이력 데이터가 롤백되지 않는, 읽기 전용이며 데이터의 크기가 크지 않을 때 사용.
- 역시나 비추천 방법.
-
참고
- 일반적으로 이력사항만 조회해야 한다면 스냅샷이 좋다. ㅠ
-
테이블 동기화 설정
-
실서버, 연계서버 또는 OLAP등의 도입으로 적절한 동기화를 해야 한다면 다음을 고려하자. (대부분 해당될것이다.)
-
상태코드 방식 : 부모 테이블마다 Update시각의 표시 => 주기적으로 배치를 돌면서 update된것만을 동기화 할 수 있다.
-
이는 Java 기본객체 상속으로 간단히 해결 가능하다.
-
-
백업테이블 방식 => 삭제의 경우 변경적재가 불가능 함으로 특정 테이블에 삭제 이력을 남기자. 이것을 참고해 동기화!
-
GenericDao사용으로 간간히 해결 가능하다.
-
-
SQL생성 => merge SQL을 자동생성해주는 Generator를 사용할것! 단순 복사는 PL/SQL의 효용성이 높다.
-
-
-
-
Identity / NonIdentity
-
Identity : 부모키가 자식테이블의 주키로 전이된다. 자식 테이블은 구분자로 사용될 추가 키를 가져야 한다.
-
강한 관계(종속관계)를 나타낸다. 부모가 없이 자식은 있을 수 없다.
-
자식 객체가 부모객체에 종속되며 자식을 필터링 해서 읽을 일(자식의 크기가 크지않다.)이 없다.
-
즉 자식이 로드되면 전량 로드된다. 자식은 독립적으로 로드될 수 없다.
-
-
@CollectionOfElements로 매핑하며 타겟은 @Embeded가 된다.
-
ex) 장바구니 객체의 자식인 ITEM 객체.
-
-
NonIdentity : 부모기가 자식 테이블의 FK로 전이된다. 자식테이블의 주키는 부모키와 상관없다.
-
약한 관계를 나타낸다.
-
자식 객체가 필터링 되어 부분만(페이징 처리) 읽어야 할 수 있다.
-
부모와 별도로 자식이 로드 가능하다.
-
@OneToMany로 매핑된다. 타겟은 부모와 동등한 @Entity이다.
-
ex) 사용자 객체의 자식인 사용자 로그인(대량의 데이터) 정보.
-
-
-
데이터베이스 상속 설정
-
반드시 Java class기준으로 상속할것 .
- 개별 트랜잭션이 어떠한 유형을 가지냐는 보통 Table보다는 class로 알 수 있다.
- List<T> 의 seq는 자바와 동일하게 0부터 시작하게 설정하자. ( null초기화가 0이 안되도록 주의! 래퍼클래스 사용할것. )
-
OneToOne Type (슈퍼타입이 개별 테이블 유지)
-
개별로 테이블로 트랜잭션이 형성됨
-
확장성이 우수하나 별개의 조인 형성
-
-
Plus Type (슈퍼 + 서브를 묶어서 하나의 테이블)
-
하나의 도메인으로 트랜잭션이 형성됨 (추천)
-
데이터 베이스 다형성( Interface)
-
Java에서 Interface를 사용하는 도메인에 해당함. (슈퍼클래스를 extend함과 동시에 interface를 구현)
-
ex) 다양한 종류의 실적은 하나의 Interface를 구현함. 징수부과는 Interface만을 사용하며 어떤 종류의 부과금인지 알지 못해도 됨.
-
-
구현체 도메인을 부모 자식으로 나눌때 부모 테이블은 1개의 키(1개의 sequence)를 가지는 테이블로 구성한다.
-
이렇게 구성하면 Interface에서 도메인 Entity로의 Fk설정이 가능하다..
-
SQL에서 각종 통계 내기 편하다.
-
-
-
-
Single Type (모든 도메인을 하나의 테이블로.. ㄷㄷ)
- 모든 도메인의 전방위에 걸쳐 트랜잭션이 형성됨
-
-
캐싱 http://erwins.springnote.com/pages/5002681
출처 : http://erwins.springnote.com/pages/2856434
04.Anddoid2010. 7. 30. 15:33
반응형