DB 정규화를 하지 않는 이유

DB 정규화를 하지 않는 이유는 한마디로 성능이다.

그렇다면 DB 정규화는 왜 성능을 해치는가?

1. DB 정규화는 테이블을 많이 나누게 하고, 테이블이 맣아지면 Join 이 많아진다. 그리고 Join 은 성능에 큰 악영향을 미친다.

1.1 Join 은 테이블 락 (Lock) 을 일으키고, 테이블 락은 병렬성의 큰 적이다.

아마 이 이유가 No-SQL 이 부상하게 된 가장 주된 원인이 아닐까 생각한다.

Python 의 GIL 이랑 같은 원리.

1.2 Join 은 여러 테이블을 가로지르는 다중 Disk-seeking 을 일으킨다. 한마디로 데이터 국지화의 적이다.

컴퓨터 하드웨어와 소프트웨어에서 많은 최적화장치들의 작동근거가 데이터 국지화이다. 이 가정이 깨질 경우 데이터 액세스가 굉장히 비싸진다.

DB 정규화는 공간을 가장 절약하는 방식이다 (i). 하지만 저장공간은 저렴하다 [1].

공간을 절약하는건 당연히 죄가 아니다. 심지어 공간을 절약해야 시간도 절약되는 경우가 많다. 그리고 이것 역시 “정규화가 성능에 좋다” 라고 주장하는 사람들의 한가지 근거이다.

하지만 알고리즘이란게 어느 선에 도달한 뒤에는 불가피하게 시간과 공간 사이의 트레이드오프에 직면하게 된다.

정규화는 공간 절약의 극한에 서있다.

이는 이론적으로도 당연하게 시간을 트레이딩 할 여지가 있음을 의미하지만, 많은 실천결과들이 역시 이 결론을 뒷받침해주고 있다.

또한 위의 1.2 와 결합시켜서 살펴보면 알게 되는데, 데이터 양을 줄인다고 무조건 시간이 절약되는게 아니라, 다수의 경우 데이터 국지화가 성능에 훨씬 큰 영향을 미친다. 이것은 실천적으로도 많이들 이중화 (Redundency) 로 정규화를 타파해 성능향상을 이룩하고 있는 산업현황과도 매칭된다.

또한 이 점은 저장 매개체의 랜덤 액세스와 순서적 액세스 사이의 수량급을 초월하는 성능 gap 의 배경속에서 더욱 확대된다. 이것은 물리적인 HDD 에서 유독 두드러지지만 SSD 에서도 상황은 비슷하다.

정규화는 쓰기에 최적화되어 있다. 하지만 읽기가 훨씬 중요하다.

특히 웹에서는 유독 그렇다. 웹에서는 읽기가 쓰기보다 압도적으로 많다.

그리고 요즘은 “모든 것이” 웹으로 이동하고 있다.

Join 은 성능 오버헤드를 의미한다.

이 조인이란 성능 코스트를 “쓰기” 를 할 때 지불할 것인가, 아니면 “읽기”를 할 때 지불할 것인가?

란 질문에서 거의 항상 “쓰기” 를 선택하는게 이득이다.

물론 아무리 모든 것이 웹으로 이동해도 당신의 프로젝트는 웹프로젝트가 아닐 수 있다. 그리고 웹인지 여부에 상관 없이 당신의 프로젝트에서는 “읽기가 쓰기보다 훨씬 중요” 란 가정이 성립되지 않을 수 있다.

“남의 가정” 이 자기에게도 맞다고 생각하는 함정에 빠지진 말자.

결론

결론은 반전이다.

위의 이유 3 에서도 얘기했지만, 그 어떤 가정도 당신의 실제 프로젝트와는 맞지 않을 수 있다는 점을 명시하자.

심지어 MongoDB 매뉴얼에서도 이런 경우에 정규화를 사용하라고 가이드하고 있다 (많은 사람들이 캐치를 안했거나 못했을 뿐):

In general, use normalized data models [3]:

  • when embedding would result in duplication of data but would not provide sufficient read performance advantages to outweigh the implications of the duplication.
  • to represent more complex many-to-many relationships.
  • to model large hierarchical data sets.

그리고 이 글에서는 요즘 시대에 잊혀져가고 있어서 유난히 강조가 필요한, 많은 사람들의 시선밖에 나가있던 DB 정규화의 장점들을 강조하고자 한다.

위에서 언급한 정규화 하지 않는 좋은 점들은 모두 사용시나리오에 대한 이런저런 가정을 바탕으로 두고 있다. 물론 이런 것들도 중요하다.

하지만 정규화가 실천적으로 중요한 원인은 그것이 범용적으로 좋은 성능을 제공하고, 사용시나리오에 대해 굉장히 열려있다는 점이다.

정규화가 이론적으로 중요한 원인은 그것이 사용 시나리오의 간섭 없이 독립적으로 어떤 모델링이 논리적으로 잘 구성되어 있는 것이며 (이럴테면 DRY (ii) ) “외력이 없는 진공속에서 물체의 운동법칙” 을 제시해주고 있다는 점이다.

DB 정규화는 우리의 종착역이 아니다. 우리는 모두 이 점을 잘 알고 있다.

우리가 잊고 있던 것은 정규화가 우리의 출발역이라는 점이다.

그리고 그 출발역은 우리의 원점이 되어, 우리가 현재 어디에 서있는가를 정의해주고 있다. 우리가 현 위치를 알고 있어야 길을 잃지 않을 것이다.

주:

(i) 양쪽 모두 압축을 도입하지 않는 전제에서.

(ii) DRY — Don’t Repeat Yourself.

P.S.

Join 이 무조건 느린건 아니다. 당연하겠지만 구체적인 데이터와도 연관되어 있고 DBMS 의 종류와 그것의 구체적인 버전 및 구현, 그리고 하드웨어 환경에 달려있다. 물론 이런 흔한 방어카드를 꺼내드는 이유는 토론 쌍방을 다시 불가지론(不可知論)의 늪속으로 끌어들이기 위함이 아니다.

Join 이 더 빠를 수 있는 한가지 경우를 생각해봤다. 독립해낸 작은 테이블이 특정 DBMS 의 구현상의 최적화에 의해 풀로 메모리에 로딩되었을 경우. 그것에 대한 테이블 락이나, 그것에 대한 별도 seeking 이 전혀 비싸지 않을 수 있다.

이는 다시 성능 얘기만 나오면 결국 토론이 흘러가는 끝방향인 “Profile! Profile! Profile!” 로만 이끌어지는데.

이 글의 결론이 강조하고 싶은 부분중의 하나이다: 프로파일링을 시작하기 적합한 출발점 역시 정규화된 상태가 아닐까 한다.

References:

[1] Why too much Database Normalization can be a Bad Thing: https://www.selikoff.net/2008/11/19/why-too-much-database-normalization-can-be-a-bad-thing/

[2] DB Basics – Database Normalization | 1NF, 2NF, 3NF: https://sqlwithmanoj.com/2009/03/25/database-normalization/

[3] Data Model Design – MongoDB Manual : https://docs.mongodb.com/manual/core/data-model-design/

[4] Database Normalization: https://en.wikipedia.org/wiki/Database_normalization

Advertisements

2 thoughts on “DB 정규화를 하지 않는 이유

  1. 좋은 글 잘 읽었습니다.
    예전엔 정규화 안하면 잡혀가는 줄 알았는데,,NOSQL 출현으로 새삼 세상이 바뀌었고,,
    관점의 변화와 다양화를 실감했네요.
    생각해보면 전에는 시키는대로 잘 따라했고 그럼 잘 하는거라 생각했는데 ,,,
    지금보니 방향에 맞춰 생각하는 걸 잊고 살았고 그러고 있구나 합니다.

    포팅팅 된 글 읽고 오늘 여러모로 감탄했습니다. 감사합니다.

댓글 남기기

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s