ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 관계형 데이터 모델링 (4)
    생활코딩 DB 2021. 11. 17. 18:11

    --------------------------------------------------------------------------------------------------------------------

    @7.1. 물리적 데이터 모델링

    여기까지 왔다

    논데모 : RDB에 맞는 이상적인 표를 만드는 것

    물데모 : 이상적인 표를 구체적인 제품에 맞는 현실적인 표로 만드는 것

     

    이 단계에서는 성능이 중요하다.

     

    어떻게 성능을 향상시킬 수 있을지?

     

    일단 당장은 응용을 조금이라도 해보는 게 좋다.

    데이터가 쌓이고 처리량이 많아져야 어디가 늘어지고 어디는 늘어지지 않는지에 대한 분별이 생기기 위함.

     

    적당한 시점에서 각 쿼리의 성능을 평가해보고 병목이 발생하는 지점을 집중적으로 해결하는 것이 바람직하다고 생각합니다

    이때 써볼만한 방법이

    find slow query [내가 쓰는 DB제품] 라고 검색.

    query가 동작할 때 특히 느려지는 쿼리가 있겠죠? 그런걸 찾을 수 있는 방법이 제품마다 다름

    어디서 병목이 발생하는지를 찾아볼 수가 있을 것임.

     

    이런 방식들을 통해 느려지는 지점을 찾았다면

    성능을 향상시키기 위한 여러가지 방법들을 적용해봐야 함.

     

    최후의 보루는 이상적으로 정규화된 표에 구조를 손을 대는 것

    이것을 역정규화, 반정규화 라고 함. denormalization

     

    이 역정규화는 혹독한 대가를 치러야함. 이런 대가를 지불해야할 만한 것인가는 내가 처해있는 상황이 무엇인가에 대해 결정

     

    역정규화를 시도하기 이전에 다른 방법을 시도해보는것이 바람직

     

    우선 고려해볼만한 방법은

    index

     

    index는 행에 대한 읽기 성능을 비약적으로 향상시킴

    대신 쓰기 성능을 비관적으로 희생시킴

     

    왜냐면 쓰기가 이뤄질 때마다 그 행이 index가 걸려있다면 입력된 정보를 정리정돈 하기 위한 복잡한 연산과정이 필요

    이 과정에서 시간이 많이 걸릴뿐만 아니라 저장공간을 더 많이 차지

     

    그럼에도 불구하고 그렇게 잘 정리정돈하면 엄청나게 빠른 속도로 읽을 수가 있다.

     

    또 index만으로 성능을 향상시키지 못했다면 DB를 이용하고 있는 application 영역에서 cache와 같은 방법을 시도해보는 것도 좋다

     

    cache : 저장하다

     

    입력에 따른 실행결과를 저장해뒀다가 나중에 동일한 입력이 들어왔을 때 사용하는걸 통해서 DB에 부하를 주지 않는 것

     

    이렇게 하면 DB가 겪게되는 부하를 획기적으로 줄여줄 수 있음.

     

    이거저거 다해도 어려움이 있다면 그때 우리가 하는게 표에 구조를 바꾸는 일종의 외과적인 수술인 역정규화를 시도

     

    --------------------------------------------------------------------------------------------------------------------

    @7.2. 역정규화 소개

    정규화를 통해서 만든 이상적인 표를 성능이나 개발의 편의성을 위해서 조작하는 것, 구조를 바꾸는 것

     

    정규화 : 쓰기의 편리함을 위해 읽기의 성능을 희생하는 것

    --표들이 여러개로 쪼개지게 되고 그 표들을 다시 사용할 땐 join을 사용하는데 join은 굉장히 비싼 작업, 읽기의 성능이 희생됨app을 운영하다보면 읽기가 자주 일어나서 정규화로 인해 성능이 느려지는 케이스가 종종 생김

     

    일단은 정규화를 한 다음에 역정규화를 하는 것.처음부터 정규화를 하지 않은 표가 좋은것이라 할 수 없음.

     

    정규화를 한다고 해서 반드시 성능이 떨어지는 것도 절대 아님

     

    수업의 진행방향 : 

    이리로 들어가면

    MySQL기반 저 표들을 만드는 sql문을 준비해놓음

     

    Origin테이블들을 문제점에 따라 이렇게 저렇게 역정규화 해볼 것.

    1.하나의 표 안에서 컬럼을 바꾸는 것.

    2.하나의 표를 여러개의 표로 쪼개는 것.

    3.테이블과 테이블 사이의 관계성을 조작해서 일종의 지름길을 만드는 것

     

    정규화는 엄격한 규칙에 따라 공정을 거쳐가듯이 처럼 순차적으로 진행하는 것

    역정규화는 어떤 규칙이 있는게 아님 딱 봤을 때 상황 판단을 해서 진행하는 것

    이러이러한 기법이 있을 수 있습니다 하는 일종의 sample

     

    --------------------------------------------------------------------------------------------------------------------

    @7.3. 역정규화 : 컬럼을 조작 (1)join을 줄이기

     

    하나의 테이블 안에서 컬럼을 조작하는걸 통해 성능을 향상시키는 방법

    성능을 향상시키는 데 있어서 중요한 대상중 하나는 join을 줄이는 것, join이 굉장히 비싼 작업

     

    topic_title의 값이 MySQL인 행의 tag이름을 알고 싶어

    문제는 왼쪽 테이블엔 tag_id가 있고실제 이름은 id값과 연결된 tag라고 하는 표에 존재 => join이 필요

     

    MySQL의 workbench라는 프로그램으로 수업함

    단계적으로 함 처음엔 select * 였음. 쿼리 짜본다음

    JOIN넣고 그 다음 컬럼 줄이고 이런식으로 중간중간 확인하면서 쿼리짜시네

     

    이렇게 해놓고 부하가 엄청 되고 개선이 필요하다 했을 때

    선택할 수 있는 방법이 여러가지가 있지만 그중에 가장 이해하기 쉬운 방법은

    topic_tag_relation을 조회할 때 아예 그 표 안에 tag_id에 해당되는 이름이 뭔지를 넣어버리는 것중복을 허용해버리는 것

    중복은 발생하지만 join을 하지 않는다.그냥 SQL문임.

    join을 안해서 훨씬 더 빠르게 데이터를 가져올 수 있게 됨

     

    이게 역정규화!정규화하기 전의 문제를 고스란히 갖게 됨. 수정하려고 하면 다 수정해야되고.. 기존의 tag테이블도 그대로 있고..

    시스템의 복잡도가 높아진다 = 프로그램이 고장나기가 더 쉬워짐 // 그럼에도 성능을 위해서 함.

    처음부터 역정규화를 하려고 정규화를 소홀히하면 안됨

     

    --------------------------------------------------------------------------------------------------------------------

    @7.4. 역정규화 : 컬럼을 조작 (2)계산을 줄이기

    저번 시간은 join줄이기

    이번 시간은 데이터를 처리하는 비용을 줄이기 위한 역정규화

     

    각각의 저자별로 몇개의 topic을 생성했는가!를 알고 싶다

     = topic테이블에 있는 author_id값들이 각각의 author_id별로 author_id가 같은 행이 몇개가 있는지 counting

    일단 이거, 뭔지 알지. 1은 몇개 2는 몇개 해야하니까 select에 author_id가 들어가있음. group by는 같은것끼리 그룹화를 시켜줌

     

    이걸 빈번하게 한다면, GROUP BY가 상당히 비싼 작업이 될 수 있다.

     

    그럼? author라고 하는 테이블에 각각의 저자가 몇개의 글을 갖고 있는지 컬럼을 추가topic테이블에 행을 추가할 때마다 author_id의 count값을 1씩 증가시키면?

    이렇게 하면 훨씬 더 빠르게 처리 가능

     

    다만 topic_count라고 하는 값을 항상 유지시켜줘야 하는 어려움이 생김역정규화를 했을 때 얻는것과 잃는 것. trade off

     

    --------------------------------------------------------------------------------------------------------------------

    @7.5. 역정규화 : 표를 쪼개기

    하나의 표를 성능을 향상 시키기위해 여러개로 쪼갬

     

    이걸 쪼갤건데컬럼을 기준으로 쪼갤 수 있고행을 기준으로도 쪼갤 수 있다

     

    ex1) 컬럼을 기준으로 분리

    이렇게 쪼갬, PK는 포함해서 쪼갬

    용량이 큰 description이라는 컬럼은 topic에 없어서 여러가지 장점들이 있음,

    성능이 향상

    저기 description이 굉장히 용량이 크고 description을 포함하거나 포함하지 않고 조회하는 오퍼레이션의 양이 굉장히 많을 때 각각 다른 컴퓨터에 저장해서 쓰기 읽기를 시키면 컴퓨터 한대로 처리하던 일을 여러대로 분산할 수 있다.

    성능이 향상 --이런걸 샤딩이라고 함.

    DB를 운영할 때, 성능에 한계가 느껴졌을 때 여러대의 컴퓨터로 scale-out하는 기법, 어렵다, 유지하기도 힘듦, 최후의 수단으로 사용해야 하는 방법

     

    ex2) 행을 기준으로 분리

    ex1은 컬럼의 숫자가 많아봐야 얼마나 많겠어요, 한계가 있는데

    행을 기준으로 분리하는 건 이론적으론 한계가 없다. 관리가 어렵긴 함

     

    여러가지 방법이 있는데

    정말 양이 1억개씩 있을 경우엔

    author_id가 1~1000까지는 topic_1000이라는 표를 쓰고

    1001~2000까지는 topic_2000 이런 테이블을 쓰게 하는 방식으로 할 수 있다

    그럼 이제 우리가 애플리케이션을 만들 때 사용자가 author_id가 1이라 하면 우리 app이 topic_1000이라는 표가 있는 서버쪽으로 쿼리를 보내서 거기에서 데이터를 추가하고 읽을 때도 마찬가지 방법으로 하는걸 통해 사용자가 누구냐에 따라 그 사람이 데이터를 저장해야 하는 표를 구분하는

     > 그럼 각각의 물리적인 서버마다 서로 다른 표를 저장하고 서로 다른 조회를 처리하는 걸 통해 무한히 많은 처리량을 소화할 수 있게 되는 것

     

    이런식으로 처리하는게 엄청나게 어렵다 노하우도 필요하고 사고 위험도 높다. 그래서 이런걸 하려면 아주 코너에 몰렸을 때 하는 것 + 여러가지 솔루션이나 방법론 같은걸 적용해서 정교하고 안전하게 처리해야함.


    테이블 역정규화는 여러대의 서버로 분산할 때 사용할 수 있는 방법

     

    ▽where을 미리 해두는 것 아냐?

     

    --------------------------------------------------------------------------------------------------------------------

    @7.6. 역정규화 : 관계의 역정규화

    join을 줄여서 지름길을 만드는 테크닉

     

    전에 했던 컬럼의 역정규화와도 비슷한 내용, 다만 FK를 추가하는 걸 통해서 join을 줄인다

     

    어떤 특정한 저자의 태그id와 태그명을 조회하고싶다!

    근데??

    이 상태잖아

    원래는 author테이블의 id값을 아는거지 이걸 topic 테이블로 가서 title.....

    아니 그전에 테이블들을 파악 해야함

    저자에 대한 author라는 테이블이 있고글에 대한 topic이란 테이블이 있다.

    topic테이블에 author_id가 있음, author_id 하나로 그 topic의 author와 name, profile알 수 있어. 테이블 따로 뺀 느낌

     --머릿속에 동그라미 두개랑 화살표를 그려

    topic테이블에 title이라는 것 하나로 tag_id와 tag name들을 알 수 있어 왜? 테이블을 따로 뺴놨거든이것도 약간 객체 같은 느낌인데??authortopictag그리고 서로를 연결하는 PK, FK가 있고

     

    그럼 author_id로 태그id와 태그명을 조회하려면 topic테이블에서 title을 가져와서그걸 topic_tag_relation 테이블에 집어넣으면 tag_id가 나오고 걔네를 tag테이블에 넣으면 name이 나오는 거겠지?

     

    □topic_tag_relation / tag 두개의 테이블을 사용하는데, 이 두개의 테이블엔 author_id값이 없기 때문에

     --역순으로 생각하심

    topic테이블까지도 join에 참여를 시켜야 합니다이 상황에서 역정규하는 방법을 살펴볼 것

     

    1.topic_tag_relation을 select

     

    2.위에다가 name값을 붙여야 하기 때문에 LEFT JOIN으로 tag 테이블 붙임

     

    3.내가 원하는건 특정 author_id 값의 tag정보. 당장은 없어서 where못 씀. 그래서 또 join

    아 이렇게 옆으로 쭉 붙여놓고 큰 테이블을 완성 시킨 뒤 하는거구나 처음 알았네

     

    4.그 다음 WHERE문과 SELECT

     

    근데 여기서! 이건 오퍼레이션이 굉장히 자주일어난다고 한다면 join이 너무 많아서 우리 시스템의 성능을 저하시킬 수 있다. > topic_tag_relation테이블에 author_id라는 컬럼을 추가할것임. 그럼 join을 줄일 수 있다.

    그럼 이제 join이 줄어든다.

    여기까지만 해도 author_id가 나옴 추가적으로 join 안 해도 됨.

    끝, 예제가 조금 마음에 안들긴 하는데 어떤 컨셉인진 전달이 되지 않았을까

     

    --------------------------------------------------------------------------------------------------------------------

    @8.수업을 마치며

    좋은 표를 만드는 방법에 대한 수업이었다.

    순수하게 이상적인 것을 향해 가다가 물리적인 모델링 단계에서 현실에 맞게 수정하는것이 저는 매우 인상적이었습니다.

    마치 인간세계에서 사상가들에 의해서 고안된 순수한 이념들이 현실을 반영하기 위해 수정되는 것과 비슷했다.

    이상적인 것이 없다면 현실은 너무나 혼란스러울 것. 이상이 현실을 외면한다면 이상은 더 이상 이상적이지 않음.

    데이터모델링은 하나의 공식이라기 보다는 문학의 고전에 가까운 것 같아요

    고전이란 좋은 작품을 모아둔 것이죠

    그 말은

    - 고전에 속한 작품은 괜찮은 작품이다.

    - 고전에 속하지 못했다고 괜찮지 않은 것은 아니다

    ∴ 데이터 모델링에서 소개하지 않은 방법론이 얼마든지 있을 수 있고 또 이곳에 소개된 방법을 차선으로 밀어내는, 무명이지만 사실은 걔가 최선인 방법론이 이제는 어딘가에 존재할지도 모른다.

    우리가 배운 지식을 엄격하게, 자신의 삶에 적용하는 것은 당연히 중요

    동시에 이런 지식을 만든 창시자들은 엄격함과는 거리가 먼 오히려 자유로운 사람들이었을 것.

    엄격하면서도 자유롭게 지식을 대해야겠다고 생각했음.

Designed by Tistory.