우선적으로 비정규화에 대해서 이야기하려고 한다. 반정 규화는 정규화된 데이터 모델링의 역으로 분할/통합/중복을 통하여 성능상 이점을 누리기 위해 하는 것이다.
하지만 비정규화는 정규화를 수행하지 않은 모델을 지칭한다. 그렇기 때문에 비정규화된 모델에서 반정 규화를 한다는 것은 의미가 없다.
반정규화
- 정규화된 엔티티, 속성, 관계에 대해서 시스템의 성능 향상과 개발과 운영의 단순화를 위해 중복, 통합, 분리 등을 수행하는 데이터 모델링 기법이다.
의도적으로 데이터의 무결성을 위협하면서 성능을 향상하는 기법이다. 그렇기 때문에 항상 데이터 무결성 위험에 노출되어 있다.
이렇게 위험을 무릅쓰고 반정 규화를 하는 이유는 조회하는 과정에서 디스크 I/O량이 너무 많아 성능이 저하되거나, 경로가 너무 멀어 JOIN으로 인한 성능 저하가 발생하거나, 칼럼을 계산하여 읽을 때 성능 저하가 예상될 때 수행한다.
기본적으로 정규화는 CRUD의 모든 성능을 향상한다. 하지만 정규화를 하는 과정을 보면 엔티티의 증가와 관계는 증가되고 속성을 많아지기 때문에 성능 저하가 발생할 수밖에 없다.
반정 규화는 실제 프로젝트에서 적용할 때 최후의 방법으로 사용한다. 그 이유는 난이도 자체도 상당히 높고 많은 경험치를 요구하며, 확실한 비즈니스에 이해와 프로세스의 이해, 트랜잭셕의 집중을 파악해야 하는 여러 작업이 동반되기 때문이다.
개발을 하다 보면 SQL문이 A4용지 3~4장을 넘어가는 SQL문을 본 적이 있을 것이다. 이러한 SQL 문의 비효율성을 느끼지만 어떠한 개발자도 그 SQL문을 튜닝하거나 자체적으로 고치려고 하지 않는다. 그 이유는 책임 때문이다. 하지만 그걸 감수하고 더 좋은 성능을 위해 과감히 뜯어고치는 개발자가 되기 위해 노력해야 한다고 생각한다. 갑자기 이야기가 샜는데 ㅋㅋㅋ
보통 반정 규화를 할때는 다른 테이블에서 조인하여 가져와야할 컬럼을 자신의 테이블에 중복하여 SQL문을 단순하게 처리하는데 많이 사용한다. 이걸 컬럼중복을 적용한다고 하는데, 가장 많이 사용한다. 하지만 반정규화를 적용할 때는 컬럼과, 테이블, 관계 3가지를 종합적으로 고려해서 적용해야 한다.
절차
1. 반정규화 대상 조사
- 범위 처리 빈도수, 대량의 범위처리 조사, 통계성 프로세스 조사, 테이블 조인 개수
2. 반정 규화가 아닌 다른 방법 고려
- VIEW 사용, 클러스터링 적용, 인덱스 조정, 응용 애플리케이션 로직 수정
3. 반정 규화 적용
- 테이블 반정 규화, 속성 반정규화, 관계 반정규화
어떤 경우 반정규화를 고려하면 좋을까?
1. 자주 사용되는 테이블에 접근하는 프로세스가 많고 항상 일정한 범위만을 조회하는 경우
2. 테이블에 대량의 데이터가 있고 대량의 데이터 범위를 자주 처리하는 경우에 처리 범위를 줄이지 않으면 성능 보장이 어려울 경우
3. 통계성 프로세스에 의해 통계 정보를 필요로 할 때 통계 테이블을 생성
4. 테이블에 많은 JOIN문을 사용하여 조회 작업이 너무나 번거로울 경우
대신 다른 방법을 고려한다면 어떠한 방법들이 존재할까?
개발자가 작성하는 SQL문은 제 각각이어서 성능 보장이 어렵다면 VIEW를 생성해 일관되게 SQL문을 제공하는 방법.
클러스터링을 통한 방법
파티셔닝 테이블을 만드는 방법
애플리케이션 로직 변경
캐시를 사용하는 방법
공유 데이터베이스를 사용하는 방법
반정 규화는 데이터 무결성을 깨드릴 가능성이 있기 때문에 조심히 사용해야 한다. 무결성이 깨지게 되면 당시에는 알아차리지 못하지만 미래에 더 큰 재앙으로 다가올 수도 있고 저장된 데이터가 전부 쓸모없어질 수도 있다고 생각한다.
반정규화를 통해 성능을 향상
반정 규화는 중복만이 방법이 아닌, 추가, 분할, 통합, 제거라는 방법도 있으며 테이블, 칼럼, 관계 전부 반정 규화 할 수 있다.
1) 만약 1:N 관계를 가진 부모 테이블의 관계가 많고 SQL문을 통해 해당 자식 테이블의 칼럼 값을 가져오는데, 특정 범위에 해당되는 값을 가져와야 한다면 많은 서브 쿼리와 조인이 발생할 것이다.
그걸 대신해서 부모 테이블에는 자식 테이블에서 필요한 칼럼을 부모에 중복 칼럼을 생성하고 특정 범위에 해당하는 값을 넣도록 만들면 쿼리는 단 몇 줄이면 된다.
이렇게 SQL문 복잡성을 단순화시키려는 경우에 사용하면 성능 이점이 있다.
2) 데이터베이스 서버가 분산 환경인 경우 네트워크 비용보다 중복 칼럼이 더 효과적인 경우 사용한다.
등등 다양한 방법이 존재한다. 다음과 같은 키워드로 구글링 해보자
"칼럼 반정 규화, 테이블 반정규화, 관계 반정 규화"
추가) 대량의 데이터에 따른 성능
대량의 데이터 때문에 성능이 문제라면 성능 문제는 야기될 수밖에 없다.
인덱스의 트리구조가 방대해지기 때문에 CRUD 할 때 디스크의 I/O를 많이 사용하여 성능이 저하된다.
또한 하나의 테이블에 많은 칼럼이 존재한다면 데이터가 디스크에 저장될 때 여러 블록을 사용하게 되므로 I/O 성능 저하를 발생시킨다.
여기서 로우의 길이가 너무 길어 지정된 블록에 데이터를 전부 저장하지 못하여 여러 개의 블록에 저장된 것을 로우 체이닝(Row Chaning) 현상이라고 한다.
로우 마이그레이션(Row Migration)은 데이터 블록에서 수정이 발생하면 수정된 데이터를 해당 블록에 저장하지 못하고 다른 블록의 빈 공간에 저장되는 방법을 말한다.
하나의 테이블에 대량의 데이터가 쌓이는 경우에는 테이블을 분할하는 방법이 있다. 이때 테이블 분할에는 수평분할과 수직분할이 존재한다.
수평분할은 column 단위로 분할한다.
칼럼이 많다면 트랜잭션이 발생할 때, 어떤 칼럼에 대해 집중적으로 발생하지는 분석해서 테이블을 분할하면 디스크 I/O자체가 감소된다. 이때 엔티티를 1:1 관계로 분할하여 칼럼을 분할시키고 관계를 통해 데이터를 가져오게 한다.
수직분할은 row 단위로 분할한다. 이 경우에는 칼럼은 적당하지만 레코드 자체가 많아서 성능이 저하될 경우이다.
데이터량이 몇천만에서 몇억 건이 되면 아무리 서버사양이 최고급이던 인덱스를 잘 활용한다고 해도 SQL문 성능이 기대한 만큼 나오기가 어렵다.
데이터베이스마다 약간의 차이가 있지만 List Partition, Range Partition, Hash Partition, Composite Partition을 적용해 볼 수 있다.
각각 파티셔닝의 종류들이기 때문에 상황에 맞게 사용하면 된다. 이 중에 가장 많이 사용하는 Range Partition만 알아보려고 한다.
파티셔닝을 적용시키는 것은 테이블을 가상 분할시켜서 하나의 테이블처럼 보이지만 실제로는 나누어진 파티셔닝 테이블을 참조해 데이터를 분산시키는 것을 말한다.
Range Partition
Program에서는 하나의 테이블을 사용하는 것처럼 보인다. 하지만 내부적으로 구분된 Range에 따라 테이블에서 트랜잭션을 처리한다. 라우팅 기능이라고 생각하면 이해가 빠를 것이다.
보통 날짜, 숫자 값으로 분리가 가능하고 각 영역별로 트랜잭션이 분리된다면 Range Partition을 적용시킨다. 이 파티셔닝의 장점은 데이터 보관 주기에 따라 삭제가 편리하다는 것이다. 데이터의 보간 기간이 지났다면 단순히 파티션 테이블을 drop 하기만 하면 된다.
'Database' 카테고리의 다른 글
제약조건 (Constraint) (0) | 2021.04.26 |
---|---|
짧) 인덱스 특성을 통한 DB 성능 향상 (0) | 2021.04.24 |
데이터 모델링 정규화(2) (0) | 2021.04.24 |
데이터 모델링 정규화 (1) (0) | 2021.04.24 |
데이터 모델링 정규화의 성능 (0) | 2021.04.23 |
댓글