2023. 6. 4. 19:53ㆍDatabase
Intro
아래 영상을 보고, 글로 정리해서 포스팅합니다.
파티셔닝이란?
데이터베이스의 테이블을 목적에 따라 작은 테이블들로 나누는 방식을 말합니다.
크게 수직 파티셔닝과 수평 파티셔닝으로 나뉩니다.
둘을 차례대로 살펴보도록 하겠습니다.
수직 파티셔닝
Column을 기준으로 테이블을 나누는 방식입니다.
아래는 게시글 정보를 저장하고 있는 일반적인 테이블입니다.
Table name: Board
id | 제목 | 작성자id | 생성 일자 | 조회 수 | 댓글 수 | content |
1 | 호식이 치킨 | leehosik | 2023-06-04 | 67 | 12 | ... |
2 | 날씨가 좋네요 | niceWeather | 2023-06-04 | 1 | 0 | ... |
만약 아래와 같은 게시글 목록을 구성하려면 필요한 데이터는
Content를 제외한 모든 컬럼일 것입니다.
쿼리문 또한 다음과 같을 것입니다.
SELECT
id, 제목, ...., 댓글 수
FROM Board
WHERE ...
하지만 테이블의 데이터를 가져올 때, HDD나 SSD에서 원하는 데이터를 전부 다 가져옵니다.
쿼리문에서 본문 내용이 없다고 해서 해당 컬럼을 제외하고 가져오는 것이 아니라, 일단 row를 통째로 가져오는 것입니다.
이후 쿼리문을 통해 필터링이 진행됩니다.
문제는 Content 컬럼의 크기는 다른 컬럼에 비해 크기가 매우 크다는 점입니다(게시글 본문이므로).
따라서 Content는 화면에서 사용하지 않을 데이터지만 일단 메모리에는 올라가야 하므로 불필요한 I/O 부담이 발생합니다.
이때 수직 파티셔닝을 사용하면 효과적입니다.
id | 제목 | 작성자id | 생성 일자 | 조회 수 | 댓글 수 |
1 | 호식이 치킨 | leehosik | 2023-06-04 | 67 | 12 |
2 | 날씨가 좋네요 | niceWeather | 2023-06-04 | 1 | 0 |
id | content |
1 | ... |
2 | ... |
원래의 테이블을 수직 파티셔닝을 이용해 분리했습니다.
무거운 content 컬럼을 따로 옮겼기때문에, 특정 게시글을 클릭했을 때 본문 내용을 요청하면 될 것입니다.
이외에도 보안에 민감한 컬럼들에 제한을 걸어서 수직 파티셔닝을 하거나, 자주 사용하는 속성들을 모아서 수직 파티셔닝을 구성할 수도 있습니다.
수평 파티셔닝
row를 기준으로 테이블을 나누는 방식입니다.
따라서 테이블의 스키마는 변동이 없습니다.
다음은 '구독' 채널의 예시입니다. 특정 사용자가 구독하고 있는 채널의 ID를 나타내고 있습니다.
Table name: Subscription
user_id | channel_id | membership |
helloWorld | 5 | ... |
ronaldo | 128 | ... |
curry | 77 | ... |
lebron | 5 | ... |
iLoveSpring | 128 | ... |
helloWorld | 300 | ... |
helloWorld | 77 | ... |
위의 테이블은 최대 (사용자 수 * 채널 수) 만큼의 row가 생성될 수 있습니다.
사용자 수자 백 만명이고, 채널 수가 1000개라면 100억개의 row가 생성되는 것이죠
이 경우 테이블이 커질수록 테이블에 걸려있는 인덱스의 크기도 증가하며, 테이블의 읽기/쓰기가 있을 때마다 인덱스에서 처리되는 시간이 늘어날 것입니다.
이 때 수평 파티셔닝을 적용하면 효과적입니다.
Hash Partition을 적용해보면(범위, 목록 등으로도 파티셔닝이 가능합니다)
user_id를 해시 함수를 돌려서 0 또는 1의 값을 얻은 뒤, 각각의 테이블에 저장하는 방식입니다.
user_id를 이용했으니 동일한 사용자의 데이터는 같은 테이블에 저장될 것입니다(해시 값이 동일하므로).
이때 user_id를 파티션 키(partition key)라고 합니다.
주의사항
파티션 키를 무엇으로 정할지 신중한 고민이 필요합니다.
위의 예제에서 특정한 사용자가 구독한 채널 정보를 얻기 위해서는 둘 중에 하나의 테이블만 조회하면 됩니다.
하지만 특정한 채널을 구독한 사용자를 얻기 위해서는 두 테이블을 조회해야 합니다.
=> 자주 사용하는 데이터를 기준으로 파티션 키를 정해야 할 것입니다.
또한, 데이터가 균등하게 분배될 수 있도록 해시 함수를 잘 정의해야 합니다. 수평 파티셔닝이 데이터를 나누려고 하는 작업이므로, 해시 함수가 적절해야 할 것입니다.
또, 이미 파티셔닝 된 테이블에 파티셔닝을 추가하는 것은 무척 어렵습니다.
위의 상태에서 0,1,2,3 총 4개의 파티셔닝으로 분리하려고 한다면 0, 1 파티셔닝에 이미 저장된 일부 데이터를 옮겨야 하기 때문입니다.
'Database' 카테고리의 다른 글
Row가 3억 개인 테이블에 column 추가/삭제하기(Online DDL) (2) | 2023.11.18 |
---|---|
AWS -> NCloud로 데이터베이스 옮기기(mysqldump, docker) (1) | 2023.06.18 |
[DB] 반정규화(Denormalization) (1) | 2023.06.04 |
[DB] 정규화(Normalization)란? (0) | 2023.05.28 |