[고민] 컬럼 수에 따른 성능 차이

호밀빵 굽는 쿼카·2022년 9월 26일
3

MySQL

목록 보기
5/5

다른 부서 팀원분이 'DB설계하실 때 컬럼이 30개 정도되면 보통 쪼개는지 궁금' 하다고 질문 주셨다.

나도 궁금 🧐❓

테이블 컬럼 수가 늘어나면 쪼갠다? 쪼개지 않는다?

인터넷에 서치한 결과,

1) 무조건 나눠라,
2) 컬럼 30개 정도는 괜찮다,
3) 데이터 타입에 따라 고민해봐라,

등등 여러 의견들이 있었다.

mysql 8.0 기준으로 4096개의 컬럼까지 MAX로 사용할 수 있다고 한다.

"There is a hard limit of 4096 columns per table, but the effective maximum may be less for a given table. The exact limit depends on"

테이블당 적정 컬럼수와 관련된 권고사항은 없다. 데이터 모델링에 따라 테이블 컬럼수도 다르고 컬럼 수 MAX로 넣어주어도 상관은 없다고 한다.

하지만, 테이블을 쪼개는 이유는 이후에 테이블 타입이 변경될때 등 한테이블에서 rebuilding 하는 것이 어렵기 때문이라고 한다. 매번 필드를 추가했을때 모든 필드에 값이 들어가지 않는 경우가 생긴다면 공간 낭비가 생길수도 있을 것이다.

정리하자면, 처음부터 쪼개서 설계하는 것이 확장에 용이하다고 한다.

테이블의 수평분할 VS 수직분할

테이블 수직 분할 : 컬럼을 기준으로 나누는것

  • 컬럼이 많아지면 로우 체이닝과 로우 마이그레이션이 많아져서 성능이 저하
  • 로우 체이닝(Row Chaining) : 길이가 너무 커서 하나의 블록에 저장되지 못하고 다수의 블록에 나누어져 저장
  • 로우 마이그레이션(Row Migration) : 수정된 데이터를 해당 데이터 블록에 저장하지 못하고 다른 블록의 빈 공간에 저장
  • 개선 : 수많은 컬럼을 동시에 조회하는 경우는 드물다. 각각의 조회 조건에 맞게 이용되는 컬럼들로 그룹을 묶어서 테이블 분할을 검토할 수 있다. 조회나 처리에 대한 분산을 가능하게 하는 칼럼들을 기준으로 테이블을 분리한다면 성능 개선에 큰 도움이 될 수 있다.

테이블 수평 분할 : row를 기준으로 나누는 것

  • 대량의 데이터가 하나의 테이블에 있으면 인덱스 정보 생성 시 부하가 커진다. 인덱스를 찾아가는 깊이(Depth)가 깊어지게 되고 인덱스의 크기가 커질수록 더 많은 성능 저하를 불러온다
  • 이때 논리적으로는 같은 테이블이지만 물리적으로 서로 다른 여러 개의 테이블 스페이스에 나누어서 저장하는 파티션 방법을 이용하면 성능 개선에 큰 도움이 된다.

기본적으로 테이블의 Row 수가 많을수록 Index에 대한 부하가 따르고, 테이블의 컬럼 수가 많을수록 I/O에 대한 부하가 걸린다. 그렇다고 모든 테이블이 분리를 통해 성능 개선의 효과를 보는 것은 아니다. 하지만 대용량이면서 성능 이슈가 있는 테이블은 분리를 통한 성능 개선을 검토해 볼 필요가 있다.

테이블의 컬럼 개수와 데이터 양을 종합적으로 판단하여 양에 따른 대용량 테이블인지 컬럼 개수에 따른 대용량 테이블인지 정리한다.

만약 컬럼 개수에 따른 것이라면, 트랜잭션의 특성에 따라 테이블을 1:1 형태로 분리하는 수직분할을 하면 된다.
반면 데이터 양에 따른 것이라면, 적절한 파티션을 선택하고 여러 개의 물리적 스페이스로 저장하는 수평분할을 하면 된다.

어떤 사람은 데이터 테이블 사용 목적에 따라 정규화를 고민해보라고 했다.
컬럼수/데이터용량 <-> 속도 는 절대적으로 반비례한다며,,

무조건 정규화 하세요...
쓰지 않을 데이터는 남기지 마세요...
로그성 데이터는 로그 디비에 남기세요...
휘발성 데이터는 항상 지워주세요.
실시간 랭킹 같은 것은 자제해주세요..

MySQL 테이블 컬럼수 증가에 따른 성능 이슈

컬럼을 늘릴때, 테이블에 인덱스를 걸어준다고 하더라도 인덱스조건에 해당하는 row 전체를 읽기 때문에 한번에 읽을 데이터의 값이 커지고 IO에 부담을 준다고 한다.

DB 컬럼은 linked list 로 구성되어있어, 인덱스를 사용하더라도 해당열 전체 값을 가져오기 때문에 컬럼이 늘어날수록 데이터 조회 비용은 늘어난다. 컬럼들이 모두 INT 등과 같이 작은 데이터타입을 다룬다면 문제는 없겠지만, VARCHAR/TEXT 등과 같이 큰 데이터타입을 다룬다면 문제가 될 것이다. '사용하지 않더라도 읽어야 하는' 일이 생길 수 있는 것.

  • 게시물을 가져올때 분리된 테이블을 JOIN 해서 가져오면 성능이 나빠지지 않아요?
    -> ( NO, 인덱스를 사용해서 정확하게 조회하면 훨씬 빠른 속도 )
    -> ( 큰 데이터를 담은 컬럼을 별도의 테이블로 분리해서 JOIN 해서 조회하기 )

컬럼수 100개로 MyISAM과 Innodb 에서 관련된 성능 테스트를 진행한 사람이 있었다. 해당블로그 결과는 이렇다. CHAR/INT 컬럼의 경우(고정크기타입) 컬럼 수를 100개까지 늘려도 성능에 무리가 없었지만 VARCHAR 컬럼의 경우(동적크기타입) IO가 slowdown 되어 성능에 큰 영향을 준다.

참고링크

profile
열심히 굽고 있어요🍞

0개의 댓글