권순용의 데이터모델링 이야기
속성(Attribute)의 도출을 확인하자 0 0 99,999+

by axiom 속성 Attribute [2015.08.07]


이 글에서는 데이터 모델링에서 속성의 도출에 대해 확인해보자. 속성을 제대로 도출했는지뿐만 아니라, 도출된 속성을 검증하는 것 또한 매우 중요하다. 데이터 모델에서 속성은 엔티티의 성격을 좌우하기 때문이다.

실제 데이터 모델을 수행하면서 잘못된 속성은 엔티티로 도출될 수 있다. 이와 같이 잘못된 속성은 데이터의 정합에 문제를 발생시킬 수 있게 된다.

속성을 검증하는 첫 번째 단계는 최소 단위로 분할했는지를 판단하는 것이다.

속성의 도출

속성을 도출함에 있어 가장 중요한 것은 업무의 최소 단위로 속성을 분리하는 것이다. 이와 같이 속성은 업무의 최소 단위로 분리하는 것이 매우 중요하며 그렇게 해야만 애플리케이션을 좀더 수월하게 작성할 수 있고 성능을 보장받을 수 있게 된다.

  • [그림 1]
  • 속성의 도출을 확인하자

예를 들어 YYYYMMDD 형식의 일자 속성을 확인해 보자. YYYYMMDD 형식의 일자 속성은 여러 가지 형태로 속성을 구성할 수 있다. 해당 일자 속성으로 만들 수 있는 속성의 경우의 수는 다음과 같다.

  • - YYYY, MM, DD
  • - YYYYMM, DD
  • - YYYY, MMDD
  • - YYYYDD, MM
  • - YYYYMMDD

위와 같이 크게 네 가지 경우의 수가 존재하며 이중 어떤 형태로 속성을 구현할지는 해당 속성을 액세스하는 업무의 성격에 달려 있다. 경우에 따라 DD만으로 업무에서 의미가 있다면 DD는 별도의 속성으로 구성해야 한다.

반면에 MM만으로 업무에서 의미가 있다면 MM은 별도의 속성으로 구성해야 할 것이다. 예를 들어, 생일날 고객의 이메일로 할인 쿠폰을 보낸다면 어떻게 되겠는가?

선 당일 생일인 고객을 조회해야 할 것이다. 이와 같은 경우에 YYYYMMDD 형태를 가지는 생일 속성을 YYYYMMDD 속성 하나로 구성했다고 가정하자. 그렇다면 [리스트 1]과 같이 SQL을 수행해야 할 것이다.

  • [리스트 1] YYYYMMDD 속성 하나로 구성한 경우
  • SELECT 고객이름, 이메일
      FROM 고객_정보
     WHERE SUBSTR(BIRTH_DAY,5,4) = SUBSTR(TO_CHAR(SYSDATE,'YYYYMMDD'),5,4);
    

이와 같이 SQL을 작성한다면 Where 조건의 컬럼이 함수에 의해 가공돼 있으므로 BIRTH_DAY 속성에 인덱스가 존재하더라도 해당 인덱스를 이용할 수 없는 것은 너무나도 자명한 일이다. 그렇기 때문에 해당 SQL은 고객_정보 테이블을 FULL SCAN하게 되어 성능은 저하될 것이다.

만약 BIRTH_DAY 속성을 DDMM으로만 구성하고 YYYY는 다른 속성으로 독립시켰다면 [리스트 1]의 SQL은 [리스트 2]와 같이 수행할 수 있을 것이다.

  • [리스트 2] BIRTH_DAY 속성을 DDMM으로만 구성하고 YYYY는 다른 속성으로 독립한 경우
  • SELECT 고객이름, 이메일
      FROM 고객_정보
     WHERE BIRTH_DAY = SUBSTR(TO_CHAR(SYSDATE,'YYYYMMDD'),5,4);
    

해당 SQL은 Where 절의 컬럼이 함수에 의해 가공되지 않았기 때문에 BIRTH_DAY 속성에 인덱스가 존재한다면 해당 인덱스를 이용해 원하는 데이터를 추출할 수 있을 것이다. 결국 속성이 업무의 최소 단위로 분리됐는지 아닌지에 따라 SQL의 수행에는 엄청난 차이가 발생하게 된다.

이와 같은 이유에서 속성은 업무의 최소 단위로 분리해야 한다. 속성 검증에서 이와 같은 사항을 검증하는 것은 매우 중요한 항목이다.

  • [그림 2]
  • 속성의 도출을 확인하자

속성 검증에서 두 번째 단계는 유일한 값을 가지는지 여부다. 해당 속성에 의해 엔티티를 구성하는 Unique Identifier가 유일할 수 있는지를 확인해야 한다.

어느 카드사에서 카드번호를 Unique Identifier로 하는 카드_정보 엔티티가 존재한다고 가정하자. 거래일자 속성을 카드_정보 엔티티에 저장한다면 어떻게 되겠는가?

하나의 카드번호 값에 대해 카드_정보 엔티티에는 하나의 거래일자 값만을 저장하게 된다. 그렇다면 해당 카드번호 값으로 발생시킬 수 있는 거래는 한 번밖에 안 된다는 의미가 될 것이다. 이와 같다면 업무가 구현될 수 없다.

그렇다면 어떻게 구성해야 하는가? 거래일자 속성을 다른 엔티티로 분할해야 할 것이다. 따라서 카드_정보 엔티티는 고객_정보 엔티티와 거래내역 엔티티로 분리될 것이다.

거래내역 엔티티는 카드번호 속성과 거래일자 속성으로 Unique Identifier로 구성한다면 하나의 카드번호 값에 여러 번의 거래가 발생할 수 있으므로 우리가 원하는 업무를 구현할 수 있을 것이다. 물론 거래일자 속성은 시분초까지 저장해 동시에 카드가 사용되는 것을 제한해야 한다.

  • [그림 3]
  • 속성의 도출을 확인하자

속성의 검증에서 세 번째 단계가 추출 값 여부를 확인하는 것이다. 추출 값은 일반적으로 속성으로 선정하는 순간 성능 및 업무 구현이 어려울 수 있다.

[그림 3]의 예제와 같이 고객 엔티티에 고객이 가입한 거래건수 속성을 도출한다면 해당 거래건수 속성에는 어떤 현상이 발생하는가? 거래내역 엔티티에 1건의 거래가 발생한다면 해당 고객번호 값을 확인해 고객 엔티티의 거래건수 속성 값을 변경해야 할 것이다.

이와 같다면 어떻겠는가? 거래내역 엔티티에 데이터가 저장되는 순간 고객 엔티티에는 Update가 발생하게 되므로 거래내역 엔티티에 대한 Insert 작업은 부하를 발생시키게 될 것이다.

또한 거래건수 엔티티는 자주 변하는 값이기 때문에 데이터 정합성에도 문제를 발생시킬 수 있다. 그리고 애플리케이션은 복잡해질 것이다.

  • [리스트 3] 추출 값을 속성으로 도출하지 않는 경우
  • SELECT COUNT(고객번호) 거래건수
      FROM 거래내역
     WHERE 고객번호 = '111'
    

이와 같은 이유에서 추출 값은 속성으로 도출하지 않는 것이 일반적이다. 거래건수 값을 추출하고 싶다면 속성으로 구현하는 것이 아니라 <리스트 3>과 같이 SQL을 수행하는 것이 유리하다.

- 강좌 URL : http://www.gurubee.net/lecture/2858

- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^

- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입