Partitioning
partitioning은 다음과 같이 vertical partitioning
과 horizontal partitioning
으로 나눌 수 있다.
vertical partitioning | horizontal partitioning |
---|---|
column을 기준으로 table을 나누는 방식 | row를 기준으로 table을 나누는 방식 |
Vertical Partitioning
예를 들어 Article
이라는 게시글관련 테이블이 있다고 해보자.
id | title | writer_id | created_at | read_cnt | comment_cnt | content |
---|---|---|---|---|---|---|
... | ... | ... | ... | ... | ... | ... |
만약 게시글들을 조회해야할 경우 content
attribute는 필요가 없고 id, title, writer_id, created_at, read_cnt, comment_cnt
만 필요로 할 것이다. 이때 SELECT
문으로 조회를 실행하면 content
를 포함하여 전체 데이터를 보조기억장치에서 불러온다. 이렇게 사용하지 않는데 사이즈가 큰 content
까지 불러오게 되면서 성능에 영향을 줄 수 있다.
이런 문제를 해결하기위해 vertical partitioning
을 할 수 있다. 즉, 다음과 같이 content
부분만 분리함으로써 게시글들을 조회할때는 id, title, writer_id, created_at, read_cnt, comment_cnt
만 불러올 수 있도록하고 특정 게시글을 조회할때 content
를 불러올 수 있도록 할 수 있다.
id | title | writer_id | created_at | read_cnt | comment_cnt |
---|---|---|---|---|---|
... | ... | ... | ... | ... | ... |
id | content |
---|---|
... | ... |
Horizontal Partitioning
유튜브처럼 채널에 대한 사용자의 구독 정보 테이블을 다음과 같다고 해보자.
user_id | channel_id | alarm | membership |
---|---|---|---|
aaa | 1 | ... | ... |
hey | 401 | ... | ... |
dingo | 395 | ... | ... |
mara | 717 | ... | ... |
lol | 1 | ... | ... |
son | 22 | ... | ... |
aaa | 28 | ... | ... |
mara | 101 | ... | ... |
aaa | 42 | ... | ... |
dingo | 42 | ... | ... |
사용자 수가 N이고 채널의 수가 M이라고 한다면 해당 테이블이 가질 수 있는 최대 N * M
만큼 가질 수 있다. 그리고 테이블의 크기가 커질 수록 인덱스의 크기도 커진다. 이로 인해 테이블의 read/write 마다 인덱스에서 처리되는 시간이 늘어날 수 있다. 왜냐하면 B-tree를 사용하는 인덱스를 기준으로 삽입/삭제시 마다 B-tree가 조정이 되기 때문이다.
이런 문제를 해결하기 위해서 horizontal partitioning
을 할 수 있다. horizontal partitioning
은 여러 방법(hash-based, range-based 등)이 있으며 hash-based 방법을 많이 사용한다고 한다.
hash-based로 horizontal partitioning
을 수행한다고 했을 때 두 개의 테이블로 나누기위해 user_id를 hash function
에 넣어서 0 또는 1
을 출력한다고 해보자. 예를 들어 user_id가 aaa
일 경우 0을 출력하고 hey
일 경우 1을 출력하도록 만드는 것이다. 그러면 다음과 같이 partitioning을 수행한 결과를 확인할 수 있다.
user_id | channel_id | alarm | membership |
---|---|---|---|
aaa | 1 | ... | ... |
dingo | 395 | ... | ... |
aaa | 28 | ... | ... |
aaa | 42 | ... | ... |
dingo | 42 | ... | ... |
user_id | channel_id | alarm | membership |
---|---|---|---|
hey | 401 | ... | ... |
mara | 717 | ... | ... |
lol | 1 | ... | ... |
son | 22 | ... | ... |
mara | 101 | ... | ... |
이 과정에서 hash function에 넣은 user_id를 partition key
라 한다.
그런데 channel_id로 조회해야할 경우는 어떻게 해야할까? user_id로 조회할 때는 hash function을 통해 출력된 값으로 인해 조회해야할 테이블을 찾을 수 있지만 channel_id는 두 테이블 모두 조회해야한다. 따라서 partition key
를 정할 때는 가장 많이 사용될 패턴에 따라 정하는 것이 중요하다. 또한 데이터가 균등하게 분배될 수 있도록 hash function을 정의하는 것도 중요하다.
Sharding
horizontal partitioning
처럼 동작한다. 하지만 sharing
은 각 partition이 독립된 DB 서버에 저장되는 것이다. 이렇게 독립된 DB 서버에 저장함으로써 백엔드 서버로부터의 요청들을 분산시켜 부하를 줄일 수 있다.
NOTE
sharding에서는 partition key를 shard key라 부르고 각 partition을 shard라 부른다.
Replication
Replication
은 하나의 DB 서버에 문제가 발생했을 경우에도 서비스가 중단되지 않도록 할 수 있다. 예를 들어 실제 서비스에서 사용하는 DB 서버와 Copy된 DB 서버를 두며 운영 DB 서버에 write가 일어나면 Copy DB 서버도 똑같이 copy가 되는 것이다. 그리고 운영 DB 서버에 문제가 발생하면 Copy DB 서버를 사용할 수 있는 것이다. (이를 fail over라 부름) 또한 조회 요청이 많을 경우 두 DB 서버에 분산시켜 부하를 줄일 수 있다. 이때 운영 DB 서버를 master/primary/leader라 부르고 copy DB 서버를 slave/secondary/replica라 부른다.
[reference]
https://www.youtube.com/watch?v=P7LqaEO-nGU&list=PLcXyemr8ZeoREWGhhZi5FZs6cvymjIBVe&index=29