Post List

2015년 1월 6일 화요일

대용량 데이터베이스 솔루션 1권 #03 단순 명료한 설계

단순 명료한 설계


위의 그림을 보면 왼쪽 그림은 좀 복잡해 보이고 오른쪽 그림은 비교적 단순해 보인다.

 왼쪽 그림 밑에 보면 Entity1, 2, 3 사이에 관계가 눈에 띄일 것이다. 저 표시는 Entity3과 1, 2의 관계는 3의 특정키는 1, 2 중 하나와만 Relation을 가진다는 의미이다. 그리고 1, 2 사이에도 관계가 있는 것을 볼 수가 있다.
 대부분의 저런 관계는 오른쪽의 Entity 1 과 같이 자기 스스로를 Recursive 하게 참조하는 것으로 표현이 가능하다.

예를 들어서 Entity 1, 2 는 부서의 조직관계를 표현한 것이고 Entity 3 은 판매실적을 나타낸 것이라고 가정해본다면, 왼쪽의 경우는 현재는 2단계로 부서의 표현이 가능하지만, 나중에 더 확장될 경우 Table Design 자체가 바뀌어야 할 것이다. 하지만 오른쪽의 경우는 Table 하나로 표현이 가능하다.

Enrirty는 크게 3가지로 나눌수 있다.

Key Entity (시조) : Relation의 중심. 수많은 자식을 탄생. 대부분의 경우 고객, 상품, 조직 이 3가지로 모든 표현이 가능함
Main Entity (원조) : 업무의 중심, 계약, 계좌
Action Entity (활동) : 세부적인 동작 및 Data


위의 그림과 같이 조직도를 표현했을 경우 1210 지점이 어느날 1200 본부 밑으로 소속되도록 변경되었다고 해보자.
잘못 Modeilng 된 케이스에서는 1210 뿐만 아니라 그 아래 모든 부서들에 대해서 다 Update를 실시해야 할 것이다.
하지만 RDBMS에서는 부모가 바뀌었다고 자식이 바뀌면 절대 안된다.
Recursive 표현으로 하면 해결된다. 1210이 부모를 참조하는 Key만 수정하면 끝난다.

Data Modeling 할때 HOW (어떻게 표현할 것인가) 에 치중을 할 것이 아니라 WHAT (무엇을 표현할 것인가 에 치중해라.
HOW는 나중에 구현할 때 고민을 해도 늦지 않다.

Modeling이 제대로 된지 확인하는 방법으로는 Extended ER-D 를 가져와서 전혀 상관없는 Table. 예를 들면 상품, 조직 사이에 끊임이 없어야 한다. 정상적인 RDB의 Modeling이라면 어느 시점에서 어디까지라도 끊임이 없어야 한다.

요소기술 리더의 역할


 대부분의 프로젝트에서 모든것을 Programmer에게 다 책임을 던져버리고 Designer 와 DBA는 거기에 대해서 잘 알지 못하는 경우가 많다. 하지만 개발자들은 언제든지 떠날수 있는 사람들이다. 그 사람이 떠났다고 해서 시스템이 잘못되었을 때 못고친다는 것은 말도 안된다.
 DBA를 잡부로서 사용할 것이 아니라 진정한 리더로 키워야 한다.

개발자의 인식전환


- 개발자들은 절차형 처리 방식에 익숙해져 있다. DFD, Flow-chart, if-else-then 등.... 하지만 SQL문은 그렇지가 않다. SQL문은 수학에서의 집합(SET)의 계념과 가깝다. 합집합, 교집합등으로 생각할수 있도록 사고전환이 이루어져야 한다.

- 잘못된 설계는 나중에 일을 엄청 어렵게 만든다. 물론 10만건 읽어와서 if-else-then 으로 처리를 해도 되긴하지만, DBMS에 엄청난 부하를 일으킨다.

- 자신이 처리과정을 직접 다 하는 것보다는 D/B Optmizer를 적극 활용하는 것이 훨씬 현명히다. DBMS가 똑똑하게 할 수 있도록 해주어야 한다.

가장 위의 ERD에서 왼쪽그림에서 Entity 3이 Entity 1,2를  Exclusive 하게 참조하는 경우에 대해서 다시 한번 얘기해 보겠다.
저 관계를 Entity 3은 계약, 1, 2는 각각 법인, 개인 이라고 가정을 했을 경우 아래와 같이 SQL문을 만들 수 있을 것이다.

SELECT NVAL(B.name, C.name)
  FROM 계약 A, 개인 B, 법인 C
 WHERE A.account = ?
     AND (B.flag = '1' AND A.id = B.id)
       OR (C.flag = 1 AND A.id = C.id)

위의 SQL문을 실행시키면 어떻게 될 것인가 ? 만약 B가 3만건이고 A가 20만건이라면
조건을 만족하는 B의 Record는 20만개씩 똑같은게 복사되어 나올 것이고, A의 Record는 3만개씩 복사되어 나올 것이다. distinct를 붙이면 되지 않느냐 ? 결과는 똑바로 나오겠지만 그만큼 DB I/O를 많이 하게 되어 결과가 아주 늦게 나온다. OR 조건을 달때는 모든 Table에 대해서 조건을 다 붙이지 않으면 어마어마한 양의 DB I/O를 유발한다는 것을 잊으면 안된다.

물론 PL/SQL 로도 처리가 얼마든지 가능하다.

DECLARE CURSOR C1
SELECT key, a, b, ....
   FROM Txn
 WHERE Txn_date = sysdate;
   OPEN C1
    LOOP
            FETCH C1 into 호스트변수;
                      INSERT into Master
                                 VALUE (key, ....)
           IF (error)
                      UPDATE Master SET ....
                         WHERE key - :key

대충 위와 같은 Logic으로 가능할 것이다. 하지만 만약 계약이 10만건이고 가정해보고 기존 고객의 경우 Update, 신규 고객의 경우 Insert를 해야하는데 업무특성상 기존고객이 훨씬 많을 것이다. 신규고객 1만건, 기존고객 9만건이라면 9만건의 Update를 위해서 10만건을 Select, 10만법 Insert, 9만번 Update를 해야 한다. 1건 처리에 0.01초라 하더라도 3000초 정도의 시간이 걸리게 된다는 말이다.

차라리 Data Modeling을 제대로 해 놓았다면 위와 같은 고생은 하지 않아도 될 것이다.

- Data는 절대 한건한건 처리해서는 안된다. 위의 PL/SQL에서의 가장 큰 치명적인 문제가 DBMS Call이 무진장 많다는 것이다. 29만번 Call을 해야한다. Insert 한번에 한건 넣고... 이래선 안된다. Insert 한방에 10만건 빵! Update도 한방에 빵! 이렇게 해야 된다. 나중에 공부하게될 Array Processing을 적용하면 더 빠르게 처리가 가능하다.

RDB 왜 쉽고도 어려운가 ?



가장 이상적인 것은 사용자는 요구만 하고 OPTIMIZER가 모든 것을 처리해 주는 것이다.
사용자가 SQL문을 DBMS에게 전송하면 아래와 같은 단계로 실행된다.

1. SQL문 파싱
   문법적으로 잘못된 것이 없는지 검색

2. 실행계획
   Data Dictionary를 활용하여 Table 인지 View 인지... 클러스터, 인덱스 유무를 검색하여
   최소 Cost, 최적의 실행 계획 1개를 찾아낸다.
   하지만 OPTIMIZER는 사람이 아니기 때문에 잘못 되었을 가능성이 많다.
   이걸 찾는것이 우리의 역할이다.
   OPTIMIZER 가 제대로 일을 못해줄때 그것을 바로 잡아줘야 한다.

3. 실행을 해서 결과를 반환한다.

우리는 문제를 내는 사람이어야지 문제를 푸는 사람이 되어서는 안된다.
문제를 푸는 Programmer는 OPTIMIZER가 되어야 한다.
그 과정에서 OPTIMIZER가 제대로 문제를 풀 수 있게 해주는 것이 우리의 역할이다.
보통 SQL문의 속도 향상을 위하여 SQL문의 WHERE 절에 있는 모든 것을 다 넣어서 INDEX를 만드는 경우를 흔히 볼 수가 있는데,
INDEX는 해당 TABLE에서 실행되는 모든 SQL문에 영향을 미치기 때문에 한가지 SQL문 만을 위한 INDEX를 생성해서는 절대로 안된다.

작가
이화식
출판
엔코아컨설팅
발매
1996.03.01
평점
블로거의 오늘의 책에 참여한 포스트 입니다

댓글 없음:

댓글 쓰기