😗
SQL Guide
  • 😀SQL 전문가 가이드의 가이드
  • 😦과목1 데이터모델의 이해
    • ⭐제1장 데이터 모델링의 이해
      • 🌠1-1-1. 데이터 모델의 이해
      • 🌠1-1-2. 엔터티(Entity)
      • 🌠1-1-3. 속성(Attribute)
      • 🌠1-1-4. 관계(Relationship)
      • 🌠1-1-5. 식별자
    • ⭐제2장 데이터 모델과 SQL
      • 🌠1-2-1. 정규화
      • 🌠1-2-2. 관계와 조인의 이해
      • 🌠1-2-3. 모델이 표현하는 트랜잭션의 이해
      • 🌠1-2-4. Null 속성의 이해
      • 🌠1-2-5. 본질식별자 vs. 인조식별자
  • 😧과목2. SQL 기본과 활용
    • ⭐제1장 SQL 기본
      • 🌠2-1-1. 관계형 데이터베이스 개요
      • 🌠2-1-2. SELECT문
      • 🌠2-1-3. 함수(FUNCTION)
      • 🌠2-1-4. WHERE 절
      • 🌠2-1-5. GROUP BY, HAVING 절
      • 🌠2-1-6. ORDER BY 절
      • 🌠2-1-7. 조인
      • 🌠2-1-8. 표준 조인
    • ⭐제2장 SQL 활용
      • 🌠2-2-1. 서브 쿼리
      • 🌠2-2-2. 집합 연산자
      • 🌠2-2-3. 그룹 함수
      • 🌠2-2-4. 윈도우 함수
      • 🌠2-2-5. Top N 쿼리
      • 🌠2-2-6. 계층형 질의와 셀프 조인
      • 🌠2-2-7. PIVOT 절과 UNPIVOT 절
      • 🌠2-2-8. 정규 표현식
    • ⭐제3장 관리 구문
      • 🌠2-3-1. DML
      • 🌠2-3-2. TCL
      • 🌠2-3-3. DDL
      • 🌠2-3-4. DCL
  • 😨과목3. SQL 고급 활용 및 튜닝
    • ⭐제1장 SQL 수행 구조
      • 🌠3-1-1. 데이터베이스 아키텍처
      • 🌠3-1-2. SQL 처리 과정
      • 🌠3-1-3. 데이터베이스 I/O 메커니즘
    • ⭐제2장 SQL 분석 도구
      • 🌠3-2-1. 예상 실행계획
      • 🌠3-2-2. SQL 트레이스
      • 🌠3-2-3. 응답 시간 분석
    • ⭐제3장 인덱스 튜닝
      • 🌠3-3-1. 인덱스 기본 원리
      • 🌠3-3-2. 테이블 액세스 최소화
      • 🌠3-3-3. 인덱스 스캔 효율화
      • 🌠3-3-4. 인덱스 설계
    • ⭐제4장 조인 튜닝
      • 🌠3-4-1. NL 조인
      • 🌠3-4-2. 소트 머지 조인
      • 🌠3-4-3. 해시 조인
      • 🌠3-4-4. 스칼라 서브쿼리
      • 🌠3-4-5. 고급 조인 기법
    • ⭐제5장 SQL 옵티마이저
      • 🌠3-5-1. SQL 옵티마이징 원리
      • 🌠3-5-2. SQL 공유 및 재사용
      • 🌠3-5-3. 쿼리 변환
    • ⭐제6장 고급 SQL 튜닝
      • 🌠3-6-1. 소트 튜닝
      • 🌠3-6-2. DML 튜닝
      • 🌠3-6-3. 데이터베이스 Call 최소화
      • 🌠3-6-4. 파티셔닝
      • 🌠3-6-5. 대용량 배치 프로그램 튜닝
      • 🌠3-6-6. 고급 SQL 활용
    • ⭐제7장 Lock과 트랜잭션 동시성 제어
      • 🌠3-7-1. Lock
      • 🌠3-7-2. 트랜잭션
      • 🌠3-7-3. 동시성 제어
Powered by GitBook
On this page
  • title: 1-2-5. 본질식별자 vs. 인조식별자 tags:
  • 과목1. 데이터 모델링의 이해
  • 제2장 데이터 모델과 SQL
  • 제5절 본질식별자 vs. 인조식별자
  • 1. 중복 데이터로 인한 품질 문제
  • 2. 불필요한 인덱스 생성

Was this helpful?

  1. 과목1 데이터모델의 이해
  2. 제2장 데이터 모델과 SQL

1-2-5. 본질식별자 vs. 인조식별자

 ---

title: 1-2-5. 본질식별자 vs. 인조식별자 tags:

과목1. 데이터 모델링의 이해

제2장 데이터 모델과 SQL

제5절 본질식별자 vs. 인조식별자

빠른 배포를 지향하는 개발 트렌드에서 개발 편의성을 위해 종종 발생하는 문제점 중 하나로 인조식별자의 남용에대해 알아보자. 개발 편의성은 증대될 수 있겠지만 이에 따라 어떤 부작용을 야기하는지를 확실히 이해하고자 한다.그전에 인조식별자와 본질식별자에 대해 무엇인지 알아보자.

엔터티는 반드시 데이터를 식별할 수 있는 속성이 존재해야 한다. 이를 우리는 식별자라고 배웠다. 식별자는대체 여부에 따라 본질식별자와 인조식별자로 분류할 수 있다.

  • 본질식별자 : 업무에 의해 만들어진 식별자

  • 인조식별자 : 업무적으로 만들어지지는 않지만 본질식별자가 복잡한 구성을 갖고 있으므로 인위적으로 만든식별자

제1장 5절에서 배운 내용이다. 그럼 본질식별자와 인조식별자를 모델로 만나보자.

[그림 I-2-21] 주문과 주문상품 모델 본질식별자

[그림 I-2-21] 주문상품 모델의 식별자가 본질식별자다. 주문상품 모델은 주문 시

구매한 상품 정보를 관리한다.

[표 I-2-13] 주문상품

주문번호
상품번호
주문수량

110001

1234

1

110001

1566

5

110001

234

2

INSERT INTO 주문상품 VALUES(110001, 1234, 1);
INSERT INTO 주문상품 VALUES(110001, 1566, 5);
INSERT INTO 주문상품 VALUES(110001, 234, 2);

크게 어려울 게 없다. 해당 주문에 구매한 상품에 대한 정보를 Insert하면 된다. 하지만 종종 다음과 같은 모델이 목격된다.

[그림 I-2-22] 주문과 주문상품 모델 인조식별자

[그림 I-2-22] 모델은 주문상품번호라는 새로운 식별자를 생성하였다. 이 식별자를 외부식별자라고 배웠다. 이와 같은 모델의 Insert 문은 다음과 같을 것이다.

INSERT INTO 주문상품 VALUES(주문상품번호SEQ.NEXTVAL, 110001, 1234, 1);
INSERT INTO 주문상품 VALUES(주문상품번호SEQ.NEXTVAL, 110001, 1566, 5);
INSERT INTO 주문상품 VALUES(주문상품번호SEQ.NEXTVAL, 110001, 234, 2);

위 SQL문은 주문상품번호SEQ'라는 시퀀스(Sequence) 객체를 생성하고 NEXTVAL 기능을 이용하여 자동으로 값을 채번하여 Insert하는 방식이다. [그림 I-2-21] 모델에 비해 전혀 좋은 점이 없다. 오히려 불필요한 시퀀스를 생성할 뿐이다. 그렇다면 왜 이런 모델을 생성하였을까? 아마도 여러 가지 이유가 있을 수 있겠으나, 가장 큰 이유는 본질식별자에 대해 고민하지 않았기 때문이다. 대체로 모델에 대한 이해도가 높지 않은 상태에서 모델을 설계하다보면, 식별자는 유일성과 존재성(Unique, Not null)만 만족하면 된다고 생각할 수 있기 때문이다. DBMS에서 기본키(Primary key)를 생성하면 Unique와 Not null 제약이 생기므로 데이터 입력 시 오류가 발생한다. 즉 데이터 입력 시 에러가 발생하는 것에 대해서만 고려하고, 실제 해당 엔터티의 본질식별자에 대한 고민을 하지 않았기 때문에 [그림 I-2-22]와 같은 모델이 만들어진다. 그럼 이번에는 조금 다른 모델의 경우를 살펴보자.

[그림 I-2-23] 주문과 주문상세 모델 본질식별자

하나의 주문에 동일상품을 중복으로 구매하고 싶다면, [그림 I-2-21] 모델에서는 불가능할 것이다. 상품번호가 중복되기 때문이다. [그림 I-2-23]의 주문상세 모델은 상품번호를 식별자로 구성하지 않고 하나의 주문에 발생하는 상품의 Count를 주문순번이라는 속성으로 식별자를 구성하였다. 이렇게 모델을 구성하면 어떤 업무의 변화가 생기는지 확인해보자.

[표 I-2-14] 본질식별자 주문상세

주문번호
주문순번
상품번호
상품명
배송지

110001

1

1234

제주감귤 1box

우리집

110001

2

1234

제주감귤 1box

부모님집

110001

3

1234

제주감귤 1box

친구집

[표 I-2-14] 데이터를 보면, 동일상품을 하나의 주문에서 처리하고 있다. 즉 쇼핑몰에서 동일한 상품을 몇 개를각기 다른 배송지에 보내고 싶은 요건을 나타낸 것이다. 충분히 있을 수 있는 요건이다. 만일 [그림 I-2-21]의주문상품 모델이라면 위와 같은 요건을 처리하기 위해서는 주문을 따로 세 번 해야 할 것이다. 실제 자주 사용하는쇼핑몰에서 주문을 해보면 동일상품 주문이 가능한 곳도, 그렇지 않은 곳도 있음을 알 수 있다. 모델에 대한 이해가되었다면, 다시 [그림 I-2-23] 모델로 개발한다고 생각해보자.

INSERT INTO 주문상세 VALUES(110001, 1, 1234, ‘제주감귤 1box', '우리집');
INSERT INTO 주문상세 VALUES(110001, 2, 1234, '제주감귤 1box', '부모님집');
INSERT INTO 주문상세 VALUES(110001, 3, 1234, ‘제주감귤 1box', '친구집');

아마도 위와 같은 SQL로 입력될 것이다. 이전 모델과 다른 점은 주문순번 값을 위해 하나의 주문에 구매하는상품의 Count를 계산하여 입력해야 한다. 이와 같은 작업은 어려운 일은 아니더라도 번거로운 작업이 추가된 것은분명한 사실이다. 그리하여 다음과 같은 모델을 종종 발견할 수 있다.

[그림 I-2-24] 주문과 주문상세 모델 인조식별자

[그림 I-2-24] 주문상세 모델은 식별자를 주문상세번호로 정의하였다. 이전 모델과 차이점은 식별자를 하나의속성으로 구성한 외부식별자로 생성하였다. 주문순번 속성이 사라졌지만 대신 주문상세번호가 생성되었다. 언뜻보면 큰 차이는 없어 보이지만 실제 개발 시 편의성이 향상되는 방식이다. 다음 데이터로 어떤 부분에서 개발의편의성이 향상되었는지 확인해 보자.

[표 I-2-15] 인조식별자 주문상세

주문상세번호
주문번호
상품번호
상품명
배송지

1

110001

1234

제주감귤 1box

우리집

2

110001

1234

제주감귤 1box

부모님집

3

110001

1234

제주감귤 1box

친구집

[표 I-2-14]와 비교하여 보면 주문순번이 주문상세번호로 바뀐 것 말고는 다른 점이 없어 보인다. 하지만 실제 해당 값을 구하는 방식을 비교해보면 차이점을 알 수 있다. 주문순번은 하나의 주문번호에 대해 구매가 일어나는 상품의 Count를 구하는 것이므로 시퀀스 객체를 활용할 수 없어 따로 작업을 해줘야 한다. 하지만 주문상세번호는 단일식별자로 구성된 키값이기 때문에 시퀀스 객체로 해결이 가능하다. 즉 시퀀스 객체만 활용한다면 따로 작업해줄 필요가 없다. 다음 SQL을 보면 더 명확하게 이해할 수 있다.

INSERT INTO 주문상세 VALUES(주문상세번호SEQ.NEXTVAL, 110001, 1234, '귤 1box', '우리집');
INSERT INTO 주문상세 VALUES(주문상세번호SEQ.NEXTVAL, 110001, 1234, '귤 1box', '부모집');
INSERT INTO 주문상세 VALUES(주문상세번호SEQ.NEXTVAL, 110001, 1234, '귤 1box', '친구집');

‘주문상세번호SEQ'라는 시퀀스 객체를 만들고 NEXTVAL을 활용하면 기본키에 대한 부분은 더이상 신경쓰지 않아도 된다. 실제 작업량이 줄어들다 보니 이러한 방식을 선호하는 것도 이해는 간다. 만일 이러한 방식에 대한 문제점이 없다면 편하게 개발할 수 있는 방식을 채택하는 것이 당연할 것이다. 그렇다면 위 방식의 문제점에 대해 알아보자.

외부식별자를 사용하는 방식에는 크게 두 가지 문제점이 있다.

  • 중복 데이터로 인한 품질

  • 불필요한 인덱스 생성

1. 중복 데이터로 인한 품질 문제

외부식별자를 사용하면 중복 데이터를 막을 수 없다. 기본키의 제약을 활용한다면 중복 데이터를 원천 차단할 수 있지만, 기본키를 인위적으로 생성한 속성으로 정의하였기 때문이다. 데이터를 보면서 확인해보자.

INSERT INTO 주문상세 VALUES(주문상세번호SEQ.NEXTVAL, 110001, 1234, '귤 1box', '우리집');
INSERT INTO 주문상세 VALUES(주문상세번호SEQ.NEXTVAL, 110001, 1234, '귤 1box', '우리집'):
INSERT INTO 주문상세 VALUES(주문상세번호SEQ.NEXTVAL, 110001, 1234, '귤 1box', '우리집');
INSERT INTO 주문상세 VALUES(주문상세번호SEQ.NEXTVAL, 110001, 1234, '귤 1box', '부모집');
INSERT INTO 주문상세 VALUES(주문상세번호SEQ.NEXTVAL, 110001, 1234, '귤 1box', '친구집');

위 SQL의 두 번째 Insert 문이 로직 오류로 인해 중복으로 발생되었다고 하자. 이럴 경우 데이터는 어떻게 저장될까? 중복된 데이터를 막을 수 있을까? 결론은 막을 수 없다. 기본키를 인위적인 인조식별자로 구성하였으므로 기본키 제약은 주문상세번호에 대해 적용되어 있기 때문이다. 그로인해 실제 데이터는 다음과 같이 저장되었을 것이다.

[표 I-2-16] 인조식별자 주문상세

주문상세번호
주문번호
상품번호
상품명
배송지

1

110001

1234

제주감귤 1box

우리집

2

110001

1234

제주감귤 1box

우리집

3

110001

1234

제주감귤 1box

부모님집

4

110001

1234

제주감귤 1box

친구집

[표 I-2-16]의 두 번째 행 데이터를 보면, 이는 중복으로 발생된 데이터임에도 저장된 것을 볼 수 있다. 왜냐하면 주문상세번호에 기본키 제약이 적용되어 있고, 주문상세번호는 시퀀스를 사용하였기에 제약에 위배된 사항이 없다. 그렇다면 [그림 I-2-24] 주문상세 모델의 본질식별자의 경우는 어떨까?

.INSERT INTO 주문상세 VALUES(110001, 1, 1234, 제주감귤 1box INSERT INTO 주문상세 VALUES(110001, 1, 1234, ‘제주감귤 1boxINSERT INTO 주문상세 VALUES(110001, 2, 1234, ‘제주감귤 1boxINSERT INTO 주문상세 VALUES(110001, 3, 1234, 제주감귤 1box우리집');우리집'); ‘부모님집');친구집');

두 번째 Insert 문을 보면 로직의 오류로 인해 동일한 Insert 문이 발생하였지만, ‘주문번호+주문순번이 식별자이기에 기본키 제약조건에 의해 두 번째 Insert 문은 에러가 발생될 것이다. 최소 위와 같은 경우는 DBMS에서 원천적으로 차단을 해준다는 것이다.

그러므로 최대한 본질식별자를 지향해야 한다. 만일 외부식별자를 사용하였다면, DBMS에서는 해당 경우를 막아줄 수 없기에 애플리케이션에서 이를 방어해주어야 한다.

2. 불필요한 인덱스 생성

본질식별자와 인조식별자를 사용했을 때 인덱스 구성에 대해 어떤 차이가 있는지 알아보자.

[그림 I-2-25] 주문과 주문상세 모델 인조식별자

주문상품 모델 데이터에 액세스한다고 가정해보자. 여러 가지 액세스 패턴이 있겠지만, 가장 기본적인 액세스 패턴을 다음 SQL과 같을 것이다.

SELECT *
  FROM 주문상품
 WHERE 주문번호 = :B1;

또는 다음 SQL과 같을 것이다.

SELECT *
  FROM 주문상품
 WHERE 주문번호 = : B1
   AND 상품번호 = : B2;

가장 기본적이면서 일반적인 액세스 패턴이다. 이러한 SQL에 대해 본질식별자로 구성하면 PK 인덱스를 활용할수 있겠지만, 인조식별자로 구성한다면 [그림 I-2-25]의 IX1과 같은 인덱스를 추가로 생성해주어야 할 것이다.즉 인조식별자를 사용한다면 불필요한 인덱스를 추가로 생성해야 하는 점을 기억해야 한다. 또한 추가로 생성한인덱스는 용량과 DML 성능에 영향을 줄 수 있음을 염두에 둬야 한다.

인조식별자를 사용했을 때 발생하는 장점과 단점에 대해 여러 사례를 들어 알아봤다. 인조식별자는 무조건 사용하지말라는 것이 아니다. 제1장 5절에서 소개한 것처럼 식별자의 속성이 너무 많아지는 경우 본질식별자와 인조식별자의장단점을 따져보고 사용하자는 것이다. 그리하여 인조식별자의 남용을 피하고 꼭 필요한 경우에만 사용하는 것이바람직하다고 할 수 있다.


Previous1-2-4. Null 속성의 이해Next과목2. SQL 기본과 활용

Last updated 3 years ago

Was this helpful?

출처 : 데이터온에어 – 한국데이터산업진흥원()

😦
⭐
🌠
https://dataonair.or.kr