'논리 DB 설계'에 해당되는 글 1건

  1. 2010.07.30 논리 DB 설계
04.Anddoid2010. 7. 30. 15:33
반응형
  1. 이하는 물리설계 전 업무분석 및 현업화의 회의를 통해 도출해야 하는 내용들이다.
  2. 경고

    1. 어플리케이션을 반드시 고려해서 설계를 진행해야 한다.

      1. PK는 단순히 DB상에서의 의미만이 아니다. 어플리케이션의 Map이나 List의 index 및 복합키 객체를 고려해야 한다.
      2. DB컬럼터입, 관계정의, 정규화 등은 모두 Class 기준으로 생성하는게 무난하다.
    2. 코드성 데이터 파악 및 이력/상속/identity/캐싱 등을 미리 고려하여 설계해야 한다.

      1. 이들은 DB만을 봤을때 크게 고려하지 않아도 되지만 어플리케이션과는 밀접한 관계가 있다.
  3. Entity 타입과  Value타입의 구분

    1. 일반적으로 RDB에서 지원하는 타입(VChar, CLob 등)이 Vaue타입이며 Entity타입은 테이블이 된다.
    2. 하지만 ORM의 도움으로 이러한 관계를 적절히 조절 / 매핑할 수 있다. (DB만 잘 알아는것 가지고는 DB설계를 잘할 수 없다!)

      1. 예를 들자면 컴포지션 타입이 있다.  이는 DB전문가가 생각해 낼 수 없는 영역이다.
  4. 디자인 패턴

    1. 롤 모델 (Pair키)

      1. 기업 + 롤을 identity하게 연결해서 거래처 라는 롤 모델을 만든다.
      2. 기업은 고객/구매자 라는 2가지 룰을 가지며 고로 거래처는 2가지 형태가 나온다.
      3. 롤은 방대하고 갱신 가능할때만 DB에서 관리한다.
      4. 명시적인 pair키를 가지기 때문에 자료를 분명하게 나타낼수는 있지만 어플에서 관리하기가 짜증난다.
    2. 거래 모델

      1. 위의 롤 모델인 거래처를 non-Identity하게 2개 묶어서 "거래"를 만든다.
      2. 이는 N:N매핑에서 브릿지 역활을 한다.
  5. 키 설정

    1. 특별한 이유가 없다면 인조키 사용을 강력하게 권장한다.

      1. We recommend that identifiers be 'synthetic', that is, generated with no business meaning. (자세한 내용은 Hibernate-ORM 분서 참조)
      2. 경험상 자연키는 항상 말썽을 일으킨다.

        1. 자연키는 유지보수와 스키마 개선이 훨씬 힘들다.
      3. PK는 바뀔수 있는것이 되면 골치아파진다. SID같은걸 PK로 두지 말자.. 가상키가 많이 사용되는 이유중 하나이다.
      4. 가상키는 만병통치약이 아니다.. 하지만 효과는 탁월하다.
      5. 인조키다 유리할때는?

        1. 후보키(PK의 개념)가 너무 많을때, 후보키가 없거나 있더라도 확장성을 고려할 때.
        2. 후보키의 길이가 클때, 후보키가 너무 많은 수의 애트리뷰트들과 관계를 맺을 때.
        3. Hibernate등을 사용할때.
      6. 인조키의 단점은?

        1. 자연키는 그 자체로도 강력한 무결성을 보장한다. 하지만 인조키는 이들 키값들이 중복되어도 오류를 내지 않고 insert된다.
    2. 그러나 이 인조키는 Unique한 속성을 보장해주지 못함으로 나머지 대리키들에 유니크 인덱스를 주어 사실상의 키 기능을 하게 한다.
    3. 원래 개념상에서 PK와 UID(Unique ID)는 다른 개념이다. 하지만 개념만 다를뿐 실제는 같기 때문에 현업의 ERD에서(ER-Win 등의 툴 포함) UID를 PK로 표기한다.
  6. 정규화 어느것이효율적?

    1. 정규화 : 해당 파트 참고.

    2. java객체가 필요한 만큼만 정규화하라. 자동으로 정규화가 될것이다.

    3. 가볍고 많은 row 보다 무겁고 적은 row가 훨씬 다루기 쉽다.(좋은건 아니다.) 명심할것!

    4. 정규형에 해당되지 않는 "계산된 값"등은 추가하지 말것!

      1. 통계형 컬럼은 특이한 경우(계산에 시간이 오래 걸림)를 제외하면 생성하지 않는다. 실시간 계산한다.

        1. ex) 자식 컬럼들의 합계 컬럼
        2. ex) 차액(A컬럼-B컬럼 하면 단순 계산되어지는) 컬럼 등
      2. "넣을땐 힘들어도 뺄때는 편하다." 라는건 나중에 생각해도 늦지않다. (이는 다분히 SQL중심적인 사고이다. 과연 편할까?)
  7. 이력 테이블 설정

    1. 반드시 현업과 상의 및 증거를 남길것!

      1. 이력 테이블 , 기간과 데이터 범위도 포함
      2. 이력의 의도 파악

        1. 이력 내용을 조회가 가능해야 한지?
        2. 특점 이력시점으로 롤백이 가능해야 하는지?
    2. 이력 유형

      1. 스냅샷 방식 (Backup테이블 방식)

        1. 변경된 데이터가 비지니스 로직에 사용되지 않을때 사용.

          1. 웬만하면 무조건 이방법을 사용할것!!
        2. 기존 로직에서 간단히 백업로직 추가 가능 (날자 , 일련번호 등 추가)
        3. 장점 : 다른 기능을 손볼 필요 없이 생성 가능 , 예정에 없었지만 이력을 남겨야 할때 유용. 대량의 데이터에 유용.
        4. 단점 : 기존 기능과는 연계성이 떨어짐. 이력을 볼려면 별도의 API를 구축해야함.

          1. ex) 이력서 제출시 개인정보를  함께 제출한다. 도중에 개인정보가 변경등록했음에도 불구하고
            이력서를 읽으면 예전의 개인정보가 나타나야하는 경우. 이러한 경우는 사용할 수 없다.
        5. 스냅샷 종류

          1. 데이터 전체를 전부 복사 (이게 일반적)
          2. 컬럼마다 테이블을 만들어서 변경시 복사
          3. 하나의 컬럼에 String 방식으로 변경분을 나열해서 기재.
      2. 상태 코드 방식

        1. 변경된 데이터가 비지니스 로직에 사용됨.
        2. 일반적인 방법으로 삭제 or 변경시 delete가 아닌 state를 변경
        3. 수정 이력의 필요시 상위Key를 생성해서 변경 이전과의 관계를 유지함.  (A -> B로 수정됨을 알림)
        4. 장점 : 복잡하지만 변경된 객체(과거이력)도 여전히 기존 로직API로 참조 가능.
        5. 단점 : select 등의 모든 로직에 추가 where 조건이 들어가야 함. 실수 유발 가능.
      3. 문자열 방식

        1. 이력시 이력 실적테이블에 물질정보가 들어가야 한다면 -> 물질정보의 PK를 가지는 대신 물질정보 자체의 정보를 복사 / 입력한다.
        2. 이력 데이터가 롤백되지 않는, 읽기 전용이며 데이터의 크기가 크지 않을 때 사용.
        3. 역시나 비추천 방법.
      4. 참고

        1. 일반적으로 이력사항만 조회해야 한다면 스냅샷이 좋다. ㅠ
      5. 테이블 동기화 설정

        1. 실서버, 연계서버 또는 OLAP등의 도입으로 적절한 동기화를 해야 한다면 다음을 고려하자. (대부분 해당될것이다.)

        2. 상태코드 방식 : 부모 테이블마다 Update시각의 표시 => 주기적으로 배치를 돌면서 update된것만을 동기화 할 수 있다.

          1. 이는 Java 기본객체 상속으로 간단히 해결 가능하다.

        3. 백업테이블 방식 => 삭제의 경우 변경적재가 불가능 함으로 특정 테이블에 삭제 이력을 남기자. 이것을 참고해 동기화!

          1. GenericDao사용으로 간간히 해결 가능하다.

        4. SQL생성 => merge SQL을 자동생성해주는 Generator를 사용할것! 단순 복사는 PL/SQL의 효용성이 높다.

  8. Identity / NonIdentity

    1. Identity : 부모키가 자식테이블의 주키로 전이된다.  자식 테이블은 구분자로 사용될 추가 키를 가져야 한다.

      1. 강한 관계(종속관계)를 나타낸다. 부모가 없이 자식은 있을 수 없다.

      2. 자식 객체가 부모객체에 종속되며 자식을 필터링 해서 읽을 일(자식의 크기가 크지않다.)이 없다.

        1. 즉 자식이 로드되면 전량 로드된다. 자식은 독립적으로 로드될 수 없다.

      3. @CollectionOfElements로 매핑하며 타겟은 @Embeded가 된다.

      4. ex) 장바구니 객체의 자식인 ITEM 객체.

    2. NonIdentity : 부모기가 자식 테이블의 FK로 전이된다. 자식테이블의 주키는 부모키와 상관없다.

      1. 약한 관계를 나타낸다.

      2. 자식 객체가 필터링 되어 부분만(페이징 처리) 읽어야 할 수 있다.

      3. 부모와 별도로 자식이 로드 가능하다.

      4. @OneToMany로 매핑된다. 타겟은 부모와 동등한 @Entity이다.

      5. ex) 사용자 객체의 자식인 사용자 로그인(대량의 데이터) 정보.

  9. 데이터베이스 상속 설정

    1. 반드시 Java class기준으로 상속할것 .

      1. 개별 트랜잭션이 어떠한 유형을 가지냐는 보통 Table보다는 class로 알 수 있다.
      2. List<T> 의 seq는 자바와 동일하게 0부터 시작하게 설정하자. ( null초기화가 0이 안되도록 주의! 래퍼클래스 사용할것. )
    2. OneToOne Type (슈퍼타입이 개별 테이블 유지)

      1. 개별로 테이블로 트랜잭션이 형성됨

      2. 확장성이 우수하나 별개의 조인 형성

    3. Plus Type (슈퍼 + 서브를 묶어서 하나의 테이블)

      1. 하나의 도메인으로 트랜잭션이 형성됨 (추천)

      2. 데이터 베이스 다형성( Interface)

        1. Java에서 Interface를 사용하는 도메인에 해당함. (슈퍼클래스를 extend함과 동시에 interface를 구현)

          1. ex) 다양한 종류의 실적은 하나의 Interface를 구현함. 징수부과는 Interface만을 사용하며 어떤 종류의 부과금인지 알지 못해도 됨.

        2. 구현체 도메인을 부모 자식으로 나눌때 부모 테이블은 1개의 키(1개의 sequence)를 가지는 테이블로 구성한다.

          1. 이렇게 구성하면 Interface에서 도메인 Entity로의 Fk설정이 가능하다..

          2. SQL에서 각종 통계 내기 편하다.

    4. Single Type (모든 도메인을 하나의 테이블로.. ㄷㄷ)

      1. 모든 도메인의 전방위에 걸쳐 트랜잭션이 형성됨
  10. 캐싱 http://erwins.springnote.com/pages/5002681


    출처 : http://erwins.springnote.com/pages/2856434

Posted by 1010