도당탕탕

Effective-SQL Better-Way-4 : 컬럼당 하나의 특성만 저장하자 본문

Database

Effective-SQL Better-Way-4 : 컬럼당 하나의 특성만 저장하자

backlo 2020. 9. 1. 17:11

데이터베이스의 관계는 오직 하나의 토픽 혹은 액션만 선정해서 기술해야 합니다. 컬럼은 관계로 정의된 주제를 기술하는 유일한 특성과 관련된 데이터를 포함해야 합니다. 또 속성은 다른 관계의 속성을 포함하는 외래키가 될 수도 있고, 이 속성은 다른 관계의 있는 일부 튜플과 연관성을 제공하기도 합니다.

유일한 특성을 가져야 하는 컬럼

만약 단일 컬럼에 특성값을 두 개 이상 저장하면 어떨까요? 제가 생각하기엔 별로 좋지 못한 생각인 것 같습니다. 그 이유는 다음과 같습니다.

검색하거나 값을 집계할 때 특성값을 분리하기가 어렵습니다. 때문에 중요한 개별 특성은 자체 컬럼에 넣는 것을 고려해야 합니다.

예를 들어보죠. 다음은 User라는 테이블입니다.

  • User 테이블
| user_id | user_name | user_address                       |
------------------------------------------------------------
|1        | 이민수     | 서울시 강서구 어떤로 16-15 310-202      |
|2        | 남궁지호    | 인천광역시 부평구 무슨로 32-150 110-1201 |
|3        | 남명운     | 서울시 동대문구 동대문로 20-15 605-1102  |
|4        | 박수지     | 대구광역시 달서구 달서로 100-54 2001-102 |
|5        | 최진희     | 부산광역시 강서구 동래로 22-11 1302-502  |

이 테이블은 다음과 같은 몇 가지의 문제점이 있습니다.

  • 불가능하지는 않지만 성을 찾기 어렵습니다.
    • 씨를 찾을 때 LIKE 연산자와 와일드카드 %를 사용할 수 있지만 남궁 인 사람도 같이 찾을 수 있습니다.
  • 이름을 검색할 때 효율성이 떨어지는 LIKE나 substring 연산자를 사용해 이름을 추출해야 합니다.
    • LIKE 연산자로 검색할 경우 전체 데이터를 스캔하는 비효율성을 초래합니다.
  • 도로명 주소, 도시, 구 등 쉽게 찾기가 어렵습니다.
  • 데이터를 그룹으로 묶으면 (join 사용), 그룹화가 된 사용자의 입맛에 맞게 추출하기 어렵습니다.

만약 위에서 말했듯이 이름과 주소를 잘게 쪼개보면 어떨까요?

CREATE TABLE Users {
  user_id int IDENTITY (1,1),
  user_first_name varchar(10),
  user_last_name varchar(3),
  user_address_city varchar(10),
  user_address_section varchar(10),
  user_address_load varchar(30),
  user_address_details varchar(50),
};

INSERT INTO Users (user_first_name, user_last_name, user_address_city, user_address_section, user_address_load, user_address_details) VALUES ('민수', '이', '서울시', '강서구', '어떤로 16-15', '310-202');
...
  • User 테이블
| user_id | user_first_name | user_last_name | ... | user_address_load | user_address_details |
-----------------------------------------------------------------------------------------------
| 1       | 민수             | 이              | ... | 어떤로 16-15       | 310-202               |
| 2       | 지호             | 남궁             | ... | 무슨로 32-150      | 110-1201              |
| 3       | 명운             | 남              | ... | 동대문로 20-15      | 605-1102              |
| 4       | 수지             | 박              | ... | 달서로 100-54      | 2001-102              |
| 5       | 진희             | 최              | ... | 동래로 22-11       | 1302-502              |

이제 컬럼당 특성이 한 개만 있음으로 하나 이상의 개발 특성에서 검색이나 그루핑을 쉽게 할 수 있습니다. 그리고 해당 특성을 재결합해야 할 경우, concat() 같은 함수로 그루핑을 새롭게 추출 할 수 있습니다.

위와 같은 예제는 바른 설계 중에 하나인데, 한가지 궁금한 것이 왜 도로명 주소와 상세 주소를 나눴을까요? 사실 합쳐도 되고 분리해도 되고 둘 다 상관없습니다. 상황과 환경에 따라 분리 기준이 나뉘죠. 토지 조사라는 요구사항이 있었다면 분리하는 게 좋을 것입니다. 만약 도로명 주소 일반 주소 구분이 필요 없다면? 합쳐도 됩니다. 중요한 건 속성을 식별할 때는 어느 부분을 미세하게 쪼갤 것인지 신중히 검토해서 결정해야 합니다.

결론

결론으로 개별 컬럼으로 분할해 특성을 잘게 쪼개면 개별 데이터 검색이나 그루핑을 수행하기가 쉽습니다. 하나의 컬럼에 2개의 특성이 있는 것보다 1개의 특성을 가지고 분할된 데이터 조각들을 재결합하는 것이 데이터베이스 설계에 가장 중요한 핵심 포인트입니다. 다음에는 왜 계산 데이터를 저장하면 좋지 않은지에 관해 공부해 보겠습니다.

Comments