도당탕탕

Effective-SQL Better-Way-9 : 데이터 웨어하우스에는 역정규화를 사용하자 본문

Database

Effective-SQL Better-Way-9 : 데이터 웨어하우스에는 역정규화를 사용하자

backlo 2020. 9. 6. 15:40

정규화된 테이블은 비정규화된 테이블보다 컬럼의 개수가 적고 저장 공간도 많이 차지하지 않기 때문에 성능이 좋아집니다. 또한 단일 공간으로 이루어진 데이터이기 때문에 갱신과 삽입이 빠르게 수행되고 중복이 없어 DISTINCTGROUP BY 사용을 현저하게 줄여줍니다.

데이터 웨어하우스에서 역정규화?

하지만 데이터 웨어하우스에서는 왜 역정규화를 사용해야 할까요? 아니 그보다 데이터 웨어하우스는 무엇일까요? 위키에서는 이렇게 말합니다.

데이터 웨어하우스(data warehouse)란 사용자의 의사 결정에 도움을 주기 위하여, 기간 시스템의 데이터베이스에 축적된 데이터를 공통의 형식으로 변환해서 관리하는 데이터베이스를 말한다.

즉 쉽게 말하면 데이터들을 수집하고 분석하는 즉 일종의 다차원 분석을 제공해주는 시스템인 것 같습니다. 여기 데이터베이스와 데이터 웨어하우스의 차이에 대해 표로 나타냈습니다.

데이터베이스 데이터 웨어하우스
온라인 트랜잭션 처리에 사용 온라인 분석 처리에 사용
사용자 데이터를 기록하기 위해 사용 사용자 히스토리를 읽기 위해 사용
CRUD R Only
정규화를 통해 중복 데이터를 줄이고 저장 공간 확보 비정규화를 통해 분석쿼리에 응답 시간을 단축
엔티티 - 관계형 데이터 - 모델링

본론으로 돌아가면 완전하게 정규화된 테이블에서 정규화된 데이터는 테이블 간 조인은 문제가 발생할 수 있습니다. 조인이 많을수록 DB 옵티마이저가 최적의 실행 계획을 찾기가 어려워 읽기 성능이 떨어질 수 있습니다.

하지만 역정규화된 데이터베이스는 읽기 기능에서 이와 같이 효율을 올려줍니다.

  1. 소수의 테이블을 사용하기 때문에 필요한 조인 횟수가 적거나 아예 없어서 SELECT문의 속도가 훨씬 빠르다.
  2. 단일 테이블을 사용하면 인덱스를 훨씬 효율적으로 사용할 수 있다.
    • 즉 테이블 전체를 직접 읽지 않고 인덱스만으로 원하는 데이터를 빠르게 걸러 내고 정렬할 수 있다.
  3. 데이터 쓰기 작업이 빈번하지 않음으로 너무 많은 인덱스가 쓰기 성능에 심각한 영향을 줄까 걱정하지 않아도 된다.
  4. 테이블에 있는 모든 컬럼을 인덱스를 만들어서 조회와 정렬 성능을 크게 높일 수 있다.

역정규화 하는 방법

역정규화 하는 방법은 어떤 게 있을까요? 일단 예를 들어보죠

  • Customer
CREATE TABLE Customer {
    customer_id int ... // primary key
    name varchar(10) ...
    ...
    employee_id int ... // foreign key 
}
  • Employee
CREATE TABLE Employee {
    employee_id int ... // primary key
    ...
}
  • Order
CREATE TABLE Order {
    order_id int ... // primary key
    ...
    employee_id int ... // foreign key
}
  1. 우선 가장 쉬운 역정규화 방법은 테이블에 있는 식별값을 복제해 조인을 없앤다.

    • 위에 예를 보면 직원과 주문 정보를 조회한다면 3개의 테이블을 조회해야 합니다. 하지만 Order에 employee_id 외래키를 두면 Order와 Employee 테이블만 조인하면 됩니다. 하지만 Customer의 정보도 알고 싶다면 다시 세 개의 테이블을 조인해야 하죠.
  2. 만약 자주 검색되는 데이터가 있다면 해당 필드를 조인하는 테이블에 컬럼을 추가한다.

    • 예를 들어 customer_name 데이터가 자주 검색된다면 Order, Customer를 조인하지 말고 Order 테이블에 customer_name 컬럼을 추가해 인덱스까지 만들면 좋습니다.
    • 물론 중복으로 인한 정규화를 위반하지만, 정보를 신속하게 찾는 목적이라면 이 방법은 아주 좋은 방법일 것입니다.
  3. 다른 테이블을 가리키는 필드를 추가한다.

    • 이렇게 하면 성능 향상뿐만 아니라 이력 정보를 관리하는 데도 도움이 됩니다. (변경된 정보 관리에 유용)
  4. 계산된 값이나 파생 값을 저장한다.

    • 금액 정보 등 계산 정보를 저장하면 조회 대상이 줄어들고, 반복적인 계산을 없앨 수 있습니다.
    • 값을 테이블에 저장해 놓으면 해당 데이터베이스에 대한 쿼리는 계산 결과가 모두 동일합니다.

하지만 4번을 보면 뭔가 이상합니다. #3 - 왜 계산 데이터를 저장하면 좋지 않은지 이해하자 해당 주제와 정반대의 의견을 내놓고 있습니다. 무엇이 맞을까요?

정답은 상황 속에 맞게 하자입니다. #3 - 왜 계산 데이터를 저장하면 좋지 않은지 이해하자 이 주제는 운영 중에 있는 데이터베이스 대상일 때 적용하면 좋습니다. CRUD가 빈번히 일어나고 트랜잭션 관리를 철저히 해야 하는 상황속에서 해당 주제가 부합되는 것이죠. 이번 주제는 데이터 웨어하우스 즉 읽기가 많은 데이터베이스에서 적용하면 좋은 케이스입니다. 따라서 상황에 맞게 사용하는 것이 좋습니다.

결론은?

역정규화를 하면 데이터 조회 성능이 훨씬 빨라지게 되고 자원 낭비를 줄일 수 있는 것을 봤습니다. 하지만 역정규화를 하기로 결정했다면 이것을 기억해야 합니다.

  1. 데이터 웨어하우스 시스템에서는 데이터 분할 및 분석 방법에 대한 요구 사항이 다양하다는 점을 기억해야 합니다.
  2. 역정규화한 내용을 문서로 잘 정리해 두어야 합니다. 즉 역정규화에 숨어 있는 로직과 처리한 단계를 자세히 기술해야 합니다.
    • 그래야 향후 조직에서 데이터를 정규화할 때 수행 담당자들이 정확한 정보를 이용 할 수 있습니다.

이렇게 제1장 데이터 모델 설계에 대한 Better way를 봤습니다. 다음에는 제2장 인덱스 설계와 프로그램적 처리의 Better way를 살펴보겠습니다.

Comments