역정규화

최건우·2023년 3월 23일
0

역정규화(denormalization)

  • 정규화를 통해 만든 테이블을 성능, 개발 편의성 등을 위해 조작하거나 구조를 바꾸는 것.
  • 정규화를 하게 되면 쓰기편리해지는 대신, 읽기의 성능을 희생하게 된다.
    • 테이블을 나누면 join을 해야 하는데, join에 드는 비용이 크기 때문.
  • 즉, 읽기가 자주 일어나는 테이블은 정규화로 인해 성능이 저하되는 경우가 있다. 이때 성능 향상을 위해 가장 마지막 수단으로 시도해볼 수 있는 것이 역정규화를 통한 구조 변경이다.
  • 그러나, 역정규화를 하기 전 반드시 정규화를 수행해야 한다. 아예 정규화를 수행하지 않은 테이블은 좋은 형태가 아니며, 정규화가 성능을 저하시킨다고 일반화할 수는 없기 때문이다.

역정규화의 장점, 단점

장점

  • 읽기에 들어가는 부하나 비용을 줄여 성능을 높일 수 있다.

단점

  • 역정규화를 할 경우 반드시 시스템의 복잡도가 훨씬 높아지고, 이는 프로그램이 고장날 가능성일 높이는 요인임을 알아야 한다.
  • 정규화하기 전의 문제를 고스란히 갖게 되기 때문이다(데이터 중복, 역정규화하기 이전의 테이블들이 그대로 남아있음 등).

컬럼을 조작해서 join을 줄이기

⬆️ 생활코딩 강의영상 중 발췌
  • 위와 같이 나눠진 테이블에서 topic_title에 연결된 tag.name들을 조회하려면, JOIN을 통해 해야 한다. 그런데 만약 JOIN이 빈번하게 발생하여 과부하가 걸려 역정규화를 통해 해소하고자 한다면 어떻게 해야 할까?
    • topic_tag_relation 테이블에 tag_id에 해당하는 tag.name을 함께 저장한다.
  • 결론적으로 테이블에는 데이터의 중복이 발생하지만, JOIN을 줄여 훨씬 빠르게 데이터를 가져올 수 있게 되었다.

컬럼을 조작해서 계산을 줄이기

테이블에 파생 컬럼을 만들어 group by, count 계산 작업을 줄인다.

⬆️ 생활코딩 강의영상 중 발췌
  • 위 테이블에서 각각의 저자가 몇 개의 글을 작성했는지를 목록으로 표현하고자 한다.
    • 이를 위해서는 원래 GROUP BY, COUNT 연산을 하는 쿼리를 작성해야 한다.
    • 이 연산들을 수행하지 않기 위해, author 테이블에 topic_count 컬럼을 추가한다.
    • topic 테이블에 데이터가 하나씩 쌓일 때마다 author.topic_count의 값을 수정해서 각 저자가 몇 개의 글을 갖고 있는지 기록한다.
    • 결론적으로 테이블에는 topic에 데이터가 추가, 삭제될 때마다 author.topic_count 컬럼의 값을 항상 관리해줘야 하는 복잡함이 생겼지만, 무겁고 복잡한 연산을 줄임으로써 훨씬 빠르게 데이터를 가져올 수 있게 되었다.

테이블을 쪼개기

컬럼 또는 행을 기준으로 테이블을 분리한다.

⬆️ 생활코딩 강의영상 중 발췌
  • (1) 컬럼을 기준으로 테이블을 분리
    • 위 테이블에 대해 두 가지 쿼리가 있다고 가정해 보자. 하나는 topic.description 컬럼을 조회하는 쿼리이고, 다른 하나는 이를 제외한 나머지 컬럼들을 조회하는 쿼리다.
    • 그런데 전자의 쿼리에 관한 topic.description은 그 자체로 크기가 아주 크고, 후자의 쿼리는 연산이 매우 복잡하다. 이 상황에서 성능을 높이기 위해 역정규화를 한다면 어떻게 할 수 있을까?
    • topic 테이블에서 description을 떼어내 topic_description 테이블로 저장한다.
  • (2) 행을 기준으로 테이블을 분리
    • topic 테이블에 데이터가 수억건 씩 쌓이고, 조회 역시 아주 빈번하게 일어난다고 생각해 보자.
    • 이 경우, 유사한 역할을 하는 테이블을 여러 개 생성한 후 일정한 기준에 따라 알맞은 테이블에 저장하는 방법을 생각해 볼 수 있다.
    • 예를 들면, 1 <= author_id <= 1000 이라면 topic_1000 테이블에, 1001 <= author_id <= 2000 이면 topic_2000 테이블에 저장하는 식이다.
    • 즉, 사용자에 따라 테이블을 구분하는 것이다.
    • 또한 분산 환경을 구축하여 물리적 서버마다 서로 다른 테이블을 저장하고 서로 다른 조회를 처리함으로써 무한히 많은 처리량을 소화할 수 있게 된다.
      • 단, 안전하고 정교하게 환경을 구축하지 않으면 사고의 위험이 아주 높아진다.
  • 만약 (1), (2)만으로는 성능 향상에 한계가 있다면, 두 테이블을 각각 다른 컴퓨터에 저장하는 샤딩(sharding: 데이터를 여러 대의 서버 컴퓨터에 분산 저장하는 기법)을 성능을 올리는 방법도 있다. 단, 서버 비용이 증가하고 유지가 어렵다.

관계의 역정규화

FK를 추가하여 JOIN을 줄인다.

⬆️ 생활코딩 강의영상 중 발췌
  • 위 예시에서 1번 저자(author_id)와 그가 사용한 tag를 조회하고자 한다.
    • WHERE문에 author_id = 1를 넣기 위해, 2회의 JOIN이 필요하다
      SELECT 
      	tag.id, tag.name
      FROM 
      	topic_tag_relation AS TTR
      LEFT JOIN tag ON TTR.tag_id = tag.id
      LEFT JOIN topic ON TTR.topic_title = topic.title
      WHERE author_id = 1;
    • 만약 topic.author_idtopic_tag_relation.author_id로 옮긴다면, 조인을 1회로 줄일 수 있다.
      SELECT 
      	tag.id, tag.name
      FROM 
      	topic_tag_relation AS TTR
      LEFT JOIN tag ON TTR.tag_id = tag.id
      WHERE author_id = 1;




* 이 내용은 생활코딩의 "관계형 데이터 모델링" 수업을 듣고 개인적인 공부를 위해 정리한 것입니다. 문제가 있다면, 지적해 주시면 감사하겠습니다!

출처:

profile
부족한 경험을 채우기 위한 나만의 기록 공간

0개의 댓글