데이터베이스를 설계할 때엔 중복엔터티를 없애야한다.
이를 정규화라고 하는데, 목적을 한마디로 하면 데이터의 중복을 최소한으로 줄이는 것이다. 이는 오랜 정설이었으며, 여전히 유용하다.
중복엔터티를 없애야 하는 이유는 다음과 같다.
- 변경할 부분이 생기면 모두 고쳐야 한다는 문제
- 불필요한 데이터 함께 삽입
- 데이터 불일치 가능성
지금까지 데이터베이스를 설계할때에는 항상 이 규칙을 지키기 위해 노력했다.
그런데 요즘 대용량 처리를 하게되면서 이부분이 조금씩 금이가기 시작했다.
- 인덱스가 만능키는 아니다
데이터의 속성에 따라 데이터를 한 테이블에 넣거나 분리한다. 분리된 연관성은 나중에 관계를 통해 다시금 불러올 수 있다. 우리가 관계지향 데이터베이스를 쓰는 가장 큰 이유이기도 하다. 그런데 테이블간의 Join을 한다는 것은 사실 꽤 큰 자원을 사용한다. 데이터가 적을때는 비교할 양이 얼마되지 않기 때문에 컴퓨터가 충분히 버티기에 가능하지만 데이터가 100만 정도쯤 넘어가면 인덱스가 없이는 실시간성 조회를 꽤 힘들어한다.
때문에 SQL튜닝을 하는데 가장많이 활용하는 방법이 바로 인덱스 생성이다. 그러나 인덱스 생성역시 자원을 필요로하며 인덱스가 많아질경우 쓰는데 속도가 느려진다. 느린 속도를 감내하느니 인덱스를 활용하는것이 맞지만 인덱스를 마구잡이로 생성하게 되면 해당 레코드가 변경될때마다 모든 인덱스가 연산을 다시 해야하기 때문에 더 많은 I/O가 일어난다.
지금 회사에서 사용하는 특정 테이블은 인덱스를 걸면 시간이 오래걸려 관련 테이블을 조회하는 서비스가 정지된다. 이미 1,000만 건이 넘었을 때부터 이런 조짐이 있었고, 지금은 이전에 비해 약 15배 이상 늘어난 상태다. 즉 인덱스를 새로 걸래야 서비스를 잠시라도 정지하지 않는한(이 시간도 얼마나 걸릴지 알 수 없다) 걸수 없는 상황이 되었다.
- Join 의 한계
시스템을 설계할 때에는 해당테이블에 데이터가 얼마나 쌓일지 대충 예상이 될 때가 있다. 그리고 특정테이블의 쏠림현상도 있다. 문제는 이 큰 테이블이 조회범위가 클수록(설상가상으로 인덱스가 걸려있지 않다면) 데이터를 처리하는데 오래걸린다. 그렇다면 데이터를 join하는건 괜찮을까? 아쉽게도 그렇지 않다. join하는 과정에서도 외래키가 걸려있다면 그 키를 이용해 조회하거나 혹은 별도 인덱스를 이용해 join을 시도하기 때문이다.
용량쏠림을 저지하기 위해 파티셔닝이나 백업 테이블로 옮기는 등의 노력을 많이하지만 유저수가 늘어날수록 이런 후처리를 더 자주해야한다. 이것은 근본적인 해결책이라 볼 수도 없고, 특히 무거워진 테이블은 건드린다는 것이 얼마나 부담인지 안다면 구태여 하고싶지 않은 작업이기도 하다.
그래서 요즘은 NoSQL식으로 관계를 생각하지 않고 저장하는 경우가 있다. 특히 1회성으로 사용해야 하지만 반드시 저장하고 있어야 하는 정보의 경우 1개의 테이블 1row 에 필요한 최소의 정보를 모두 넣는다. 가령 고객정보와 매출정보는 각각의 테이블이 있지만 특정 조건한에서는 두개의 정보를 하나에 넣는것이다. 이렇게 함으로써 용량이 큰 테이블을 join하지않고 해당 테이블 내 정보로 해결하는 방법을 종종 사용한다.
- 데이터 갱신에 대한 문제는 없는지?
잠깐 설명했지만 이 테이블의 용도는 재사용이 없는 로그성 테이블이자 동시에 핵심데이터이다. 즉 1번 실행하고 그것이 제대로 실행되었다면 다시 업데이트 하지 않을 데이터로 채웠다.그렇기 떄문에 다른 관련 테이블의 특정 항목이 업데이트 되었다 하더라도 이 테이블의 정보와 매칭시킬 필욘 없다. 당시에 저장된 정보나 상태값이 내겐 필요한 것이기 때문이다. 로그테이블을 만들때 이처럼 당시 상황을 나타내는 지표값을 그대로 저장하는 경우가 많은데 그것을 응용한 것이다. 즉 로그+실시간 의 장점을 가져온 테이블 이랄까. 이렇게 함으로써 join을 하면서 발생하는 비용을 줄였다.
최근에 다른 회사의 DBMS에서 내가 가진 포인트의 잔액을 계산하는데 항상 원장데이터의 row를 모두 sum하는 형태로 가져오는 것이다. 이럴경우 DBMS는 매 조회시마다 row의 값을 더하고 빼야하며 그 과정에서 cpu 사용량은 필연적으로 올라간다. 거래정보가 많아질수록 연산량은 늘어날 것이고 사용하는 자원이 늘어나는것은 자명하다. 이처럼 관계형 DBMS의 목적이나 철학이 기존과 다르다 할지라도 상황에 따라 그것을 변형해서 써야하는 순간은 온다. 그렇기에 이론공부를 소홀히 해선 안되지만 마찬가지로 응용력도 충분히 키워두는게 좋다.
'공부 > 프로그래밍' 카테고리의 다른 글
[springboot] Spring batch 테스트 시 사용하는 JobLauncherTestUtils 쓸 때 설정법 (0) | 2019.03.29 |
---|---|
[python3] Flask-SQLAlchemy 사용 시 json 으로 데이터 가공하기 (0) | 2019.03.11 |
[python3] jupyter 사용시 Connecting to kernel 문제 (3) | 2019.03.03 |
[Spring] 환경에 따라 logback 설정파일 분리하기(springboot 아님) (0) | 2019.02.26 |
[Retrofit2] Unable to create converter for interface 에러 (0) | 2019.02.21 |
댓글