본문으로 건너뛰기

반정규화

정보처리기사 목차정규화레슨 86 / 233

목차

반정규화(denormalization)는 조회 속도를 올리려고 정규화한 표를 일부러 되돌려 중복을 허용하는 일입니다. 테이블 병합·테이블 분할·중복 테이블 추가·중복 열 추가 네 가지 기법이 있습니다.

정규화는 같은 사실을 한 곳에만 적게 해 이상 현상을 없앴습니다. 값을 고칠 때는 한 곳만 고치면 되니 편합니다. 그런데 읽을 때는 거꾸로 일이 늘어납니다. '누가 무슨 과목을 몇 점 받았나'를 학과 이름까지 붙여 읽으려면 표 넷을 이어야 합니다. 학사 시스템이 이 화면을 하루에 수만 번 보여 준다면, 표를 잇는 일이 쌓여 느려집니다. 그래서 읽기가 잦은 곳만 골라 중복을 되돌립니다. 이것이 반정규화입니다.

6단계 중 1단계. 3정규형으로 나눈 네 표에서 '누가 무슨 과목을 몇 점 받았나'를 학과 이름까지 붙여 읽으려면 표 넷을 이어야 합니다.

그림은 앞 레슨에서 3정규형으로 나눈 네 표(학과·학생·과목·수강)에서 시작합니다. 수강 한 행에 학생 이름과 학과명, 과목명을 붙여 읽으려면 수강에서 학생으로, 학생에서 학과로, 수강에서 과목으로 세 번 이어야 합니다. 표를 잇는 일을 조인(JOIN)이라 합니다. 조인의 문법은 14단원에서 배웁니다. 더 보기: 조인 아래 네 절이 그 조인을 줄이는 기법 넷과, 줄이는 대신 치르는 값입니다.

1조인을 없애는 둘 — 테이블 병합과 중복 열 추가

테이블 병합은 자주 같이 읽는 두 표를 하나로 합치는 기법입니다. 학생과 학과를 합쳐 학생목록 표를 만들면 그 조인 하나가 사라집니다. 대신 '컴퓨터'가 세 행, '공학관'이 여섯 행에 적힙니다.

중복 열 추가는 옆 표에서 자주 꺼내 쓰는 열을 이 표에도 적어 두는 기법입니다. 수강 표에 과목명을 적어 두면 과목 표를 잇지 않아도 과목 이름을 읽습니다. 자료에 따라 컬럼 중복이나 중복 속성 추가라고도 부릅니다. 표를 합치지 않고 열 하나만 베껴 두는 점이 테이블 병합과 다릅니다. 과목 이름이 바뀌면 적어 둔 곳을 모두 찾아 고쳐야 합니다.

2중복 테이블 추가 — 미리 구해 둔다

중복 테이블 추가는 자주 묻는 결과를 미리 구해 표로 두는 기법입니다. 학과별 학생 수를 미리 세어 학과요약 표에 두면 읽을 때 묶어 세는 일을 하지 않습니다. 원본인 학생 표가 바뀌면 요약 표를 다시 만들어야 합니다.

3테이블 분할 — 열로 가르거나 행으로 가른다

테이블 분할은 큰 표를 갈라 한 번에 읽는 양을 줄이는 기법입니다. 열이 많은 표를 자주 읽는 열과 드물게 읽는 열로 가르는 것이 수직 분할이고, 행이 아주 많은 표를 연도나 지역처럼 기준을 정해 가르는 것이 수평 분할입니다.

4되돌릴 때 치르는 값

반정규화는 읽기를 빠르게 하는 대신 중복을 늘립니다. 중복이 늘면 고칠 곳이 여러 군데가 되어 갱신 이상의 위험이 돌아오고 저장 공간도 늘어납니다. 그래서 먼저 정규화를 마치고, 읽기가 잦아 느려지는 곳만 골라 되돌립니다.

예제

테이블 병합 — 두 표를 하나로

학생과 학과를 합쳐 학생목록 한 표로 만든 뒤, 건물이 '공학관'인 학생을 꺼냅니다. 표를 만들고 잇는 문법(CREATE TABLE·조인)은 13·14단원에서 배우니, 여기서는 결과 표만 보면 됩니다.

SQL로 확인하기

CREATE TABLE … AS SELECT⁠는 조회 결과를 그대로 새 표로 만듭니다. 학과가 없는 강도현(107)도 남기려고 LEFT JOIN으로 잇습니다. 블록 하나만 복사해 돌려도 되도록 블록마다 표를 새로 만듭니다.

CREATE TABLE 학생목록 AS
SELECT S.학번,
  S.이름,
  S.학과코드,
  D.학과명,
  D.건물
FROM 학생 S
  LEFT JOIN 학과 D
  ON D.학과코드
    = S.학과코드;
SELECT *
FROM 학생목록
WHERE 건물 = '공학관'
ORDER BY 학번;
학번이름학과코드학과명건물
101김민수CS컴퓨터공학관
102이서준CS컴퓨터공학관
103김지민CS컴퓨터공학관
104박서연EE전자공학관
105최민준EE전자공학관
106정하윤EE전자공학관

학과 표를 잇지 않고 한 표에서 건물로 걸렀습니다. 그 대신 '공학관'이 여섯 행에 적혀 있습니다. 공학관 이름이 바뀌면 여섯 행을 모두 고쳐야 합니다. 강도현(107)은 학과가 없어 건물도 NULL이라 이 결과에 나오지 않습니다.

중복 열 추가 — 옆 표의 열을 적어 둔다

수강 표에 과목명을 적어 둔 수강과목 표를 만듭니다. 과목 표는 그대로 둡니다. 101의 수강 행을 꺼내면 과목 표를 잇지 않고도 과목 이름이 함께 나옵니다.

SQL로 확인하기
CREATE TABLE 수강과목 AS
SELECT E.학번,
  E.과목코드,
  C.과목명,
  E.점수
FROM 수강 E
  JOIN 과목 C
  ON C.과목코드
    = E.과목코드;
SELECT *
FROM 수강과목
WHERE 학번 = 101
ORDER BY 과목코드;
학번과목코드과목명점수
101DS자료구조85
101NW네트워크80
101OS운영체제75

과목 표를 잇지 않고 과목 이름을 읽었습니다. 수강 12행에 '자료구조'는 4번, '네트워크'는 5번, '운영체제'는 3번 적힙니다.

중복 테이블 추가 — 미리 세어 둔다

학과별 학생 수를 미리 세어 학과요약 표에 둡니다. 학생이 없는 경영 학과는 0으로 남습니다.

SQL로 확인하기

COUNT(S.학번)은 학번 값이 있는 행만 세므로 경영 학과가 0이 됩니다.

CREATE TABLE 학과요약 AS
SELECT D.학과코드,
  D.학과명,
  COUNT(S.학번) AS 학생수
FROM 학과 D
  LEFT JOIN 학생 S
  ON S.학과코드 = D.학과코드
GROUP BY D.학과코드,
  D.학과명;
SELECT *
FROM 학과요약
ORDER BY 학과코드;
학과코드학과명학생수
BA경영0
CS컴퓨터3
EE전자3

학과별 학생 수를 물을 때마다 학생 표를 묶어 세지 않고 이 표에서 읽습니다. 학생이 들어오거나 나가면 요약 표의 학생수가 실제와 어긋나므로 다시 만들어야 합니다. 묶어 세는 문법은 13단원에서 배웁니다. 더 보기: 그룹과 집계: GROUP BY·HAVING

기법과 맞바꾸는 것

아래 표를 보기 전에, 다음 세 상황에 어느 기법을 쓸지 먼저 골라 보세요.

  • (가) 주문 표는 열이 서른 개인데, 목록 화면은 주문번호·주문일·금액 세 열만 읽습니다.
  • (나) 주문 목록 화면에 고객 이름을 함께 보여 주려고 고객 표를 늘 함께 읽습니다.
  • (다) 관리자 화면이 '오늘 매출 합계'를 10초마다 다시 보여 줍니다.
가르는 기준테이블 병합테이블 분할중복 테이블 추가중복 열 추가
무엇을 하나표 둘을 하나로 합친다표 하나를 열이나 행 기준으로 가른다집계 결과를 새 표로 둔다옆 표의 열 하나를 적어 둔다
표 수가줄어든다늘어난다늘어난다그대로
무엇이 줄어드나조인한 번에 읽는 양묶어 세는 일조인
무엇이 늘어나나합친 쪽 열의 중복같은 키가 여러 표에원본과 어긋날 위험적어 둔 열의 중복
상황(나)(가)(다)(나)

(가)는 자주 읽는 세 열만 따로 두는 수직 분할입니다. (나)는 고객 표를 주문 표에 합치는 테이블 병합으로도, 고객 이름 열만 주문 표에 적어 두는 중복 열 추가로도 풀 수 있습니다. 합치면 조인이 사라지는 대신 고객의 나머지 열까지 주문마다 적히고, 열만 적어 두면 고객 표는 그대로 남습니다. (다)는 합계를 미리 구해 두는 중복 테이블 추가입니다.

시험 포인트

  • 필기: 반정규화는 조회 성능을 올리려고 일부러 중복을 허용하는 일이고, 정규화를 마친 뒤 읽기가 잦은 곳에만 합니다. 기법은 테이블 병합·테이블 분할(수평·수직)·중복 테이블 추가·중복 열 추가입니다. 얻는 것은 조인과 묶어 세는 일이 줄어 읽기가 빨라지는 것이고, 잃는 것은 중복 때문에 갱신 이상의 위험과 저장 공간이 늘어나는 것입니다. 상황을 주고 기법 이름을 고르는 문제, 장단점을 고르는 문제로 나옵니다.
  • 실기: 반정규화(Denormalization, 자료에 따라 역정규화).

확인 문제

1. 다음 가운데 테이블 수직 분할에 해당하는 것을 고르세요.

  • ① 자주 같이 읽는 두 표를 하나로 합쳐 조인을 없앤다
  • ② 열이 서른 개인 표를 자주 읽는 열과 드물게 읽는 열로 갈라 표 둘로 만든다
  • ③ 행이 천만 개인 표를 연도별로 갈라 표 여럿으로 만든다
  • ④ 지점별 매출 합계를 미리 구해 둔 표를 따로 만든다
정답

②입니다. 분할은 가르는 기준으로 이름이 갈립니다. 열을 기준으로 가르면 수직 분할입니다.

  • ① 가르기와 합치기를 바꿔 봤습니다. 두 표를 하나로 만드는 것은 테이블 병합입니다.
  • ③ 분할의 두 방향을 바꿔 봤습니다. 행을 기준으로 가르면 수평 분할입니다.
  • ④ 표가 새로 생기는 것을 모두 분할로 봤습니다. 집계 결과를 미리 구해 새 표로 두는 것은 중복 테이블 추가입니다.

2. 쇼핑몰이 상품 목록 화면을 열 때마다 표 넷을 이어 읽느라 느려졌습니다. 그래서 설계를 일부러 되돌려 같은 값을 여러 곳에 두기로 했습니다. 이 일의 이름을 한글 이름과 영문으로 함께 쓰세요. 답을 끝까지 쓴 뒤 정답을 펼치세요.

정답

받는 답: 반정규화(Denormalization)

실마리는 '읽기가 느려서', '설계를 일부러 되돌려', '같은 값을 여러 곳에'입니다. 중복을 없애는 쪽이 아니라 되돌리는 쪽입니다.

  • 같은 이름의 다른 꼴: 역정규화 — 자료에 따라 그렇게 부르므로 함께 받습니다. 영문은 같습니다.
  • 틀리는 꼴 정규화(Normalization): 중복을 없애려고 표를 나누는 쪽입니다. 이 문제는 그 결과를 되돌렸습니다.
  • 틀리는 꼴 Denormalize: 품사가 다른 꼴입니다. 일의 이름이라 Denormalization으로 씁니다.

3. 예제의 수강과목 표를 만들어 둔 뒤, 자료구조의 이름을 '자료구조론'으로 바꿨습니다. 수강과목 표의 과목명은 어떻게 될까요?

SQL로 확인하기
CREATE TABLE 수강과목 AS
SELECT E.학번,
  E.과목코드,
  C.과목명,
  E.점수
FROM 수강 E
  JOIN 과목 C
  ON C.과목코드
    = E.과목코드;
UPDATE 과목
SET 과목명 = '자료구조론'
WHERE 과목코드 = 'DS';
SELECT DISTINCT 과목코드,
  과목명
FROM 수강과목
WHERE 과목코드 = 'DS';
정답

'자료구조'로 그대로 남습니다.

과목코드과목명
DS자료구조

중복 열은 만들 때 베껴 둔 값입니다. 원본인 과목 표를 고쳐도 따라 바뀌지 않습니다. 수강과목 표에서 과목코드가 DS인 행 4개도 함께 고쳐야 두 표의 이름이 맞습니다. 하나라도 빠뜨리면 갱신 이상입니다. 반정규화로 되살아나는 위험이 바로 이것이라, 중복을 둔 곳은 함께 고치는 일까지 정해 두어야 합니다.

더 자세히: SQLD의 정규화는 사원·부서 표로 정규화와 반정규화를 한 번에 봅니다.

끝까지 내려오면 저절로 표시됩니다. 이 기기에만 저장합니다.

정보처리기사 목차로