데이터베이스 파티셔닝 종류 및 설명
파티셔닝(Partitioning)은 대용량 데이터를 효율적으로 관리하고, 데이터 조회 및 쓰기 작업의 성능을 향상시키기 위해 테이블을 더 작은 단위로 나누는 기술이다. 파티셔닝은 크게 **버티컬 파티셔닝(Vertical Partitioning)**과 **호리즌탈 파티셔닝(Horizontal Partitioning)**으로 나뉜다.
1. 버티컬 파티셔닝 (Vertical Partitioning)
버티컬 파티셔닝은 **컬럼(column)**을 기준으로 테이블을 분할하는 방식이다. 이를 이해하기 위해 먼저 데이터베이스의 정규화(Normalization) 개념을 살펴볼 필요가 있다.
1-1. 정규화(Normalization) 개념
정규화는 데이터베이스에서 중복된 데이터 저장을 방지하고, 등록, 업데이트, 삭제 시 이상 현상(anomaly)을 예방하기 위해 사용되는 방법이다. 정규화를 수행하면 하나의 테이블이 컬럼을 기준으로 나뉘게 되는데, 이 과정 자체를 버티컬 파티셔닝이라고도 할 수 있다.
1-2. 버티컬 파티셔닝의 필요성 및 예시
버티컬 파티셔닝은 성능 최적화를 위해 사용된다. 예를 들어 Article이라는 테이블이 있다고 가정하자.
Article (id, title, writer_id, created_at, read_cnt, comment_cnt, content)
이 테이블은 하드디스크(HDD)나 SSD에 저장되며, 데이터를 읽어올 때 일반적으로 로우(row) 단위로 전체 데이터를 메모리에 올린 후 필요한 컬럼을 필터링한다.
문제는 content 컬럼이 매우 큰 데이터를 포함할 수 있다는 점이다. 작성자가 긴 글을 작성했다면 content 컬럼의 데이터 크기는 상당히 커질 것이다. 이런 경우 전체 데이터를 메모리에 올리면 불필요한 I/O 작업이 발생하여 성능 저하를 초래할 수 있다.
해결 방법: 버티컬 파티셔닝
이 문제를 해결하기 위해 content 컬럼을 별도의 테이블로 분리할 수 있다.
- Article_Main: (id, title, writer_id, created_at, read_cnt, comment_cnt)
- Article_Content: (id, content)
이렇게 나누면 content 데이터를 자주 조회하지 않을 때 불필요한 I/O 작업을 줄여 성능 향상이 가능하다.
버티컬 파티셔닝은 정규화된 테이블에서도 추가적인 성능 최적화를 위해 사용할 수 있다. 다음과 같은 경우에 유용하다:
- 민감한 정보를 별도로 관리하여 접근을 제한할 때
- 자주 사용하는 컬럼을 분리하여 조회 성능을 향상시킬 때
- 자주 사용하지 않는 컬럼을 분리하여 테이블 크기를 줄일 때
전체 데이터를 필요로 할 때는 JOIN을 통해 결합하여 조회할 수 있다.
2. 호리즌탈 파티셔닝 (Horizontal Partitioning)
호리즌탈 파티셔닝은 **로우(row)**를 기준으로 테이블을 분할하는 방식으로, 테이블의 **스키마(schema)**는 그대로 유지된다.
2-1. 호리즌탈 파티셔닝의 필요성 및 예시
예를 들어 Subscription이라는 테이블이 있다고 가정하자.
Subscription (user_id, channel_id, alarm, membership)
이 테이블이 가질 수 있는 최대 데이터 수는 다음과 같다:
- 사용자 수 (N)
- 채널 수 (M)
- 최대 구독 수: N * M
예를 들어:
- 사용자 수: 1백만 명 (1M)
- 채널 수: 1천 개 (1K)
- 최대 구독 수: 10억 개 (1G)
이처럼 테이블의 데이터가 많아질수록 인덱스 크기도 커지며, 인덱스를 검색하는 시간이 길어져 조회 및 쓰기 성능이 점점 저하된다. 특히 테이블에 데이터를 삽입, 수정, 삭제할 때마다 B-Tree 구조가 조정되므로, 테이블 크기가 클수록 인덱스 유지 비용이 증가한다.
해결 방법: 호리즌탈 파티셔닝
이 문제를 해결하기 위해 테이블을 여러 개로 나눌 수 있다. 여기서 **해시 기반 파티셔닝(Hash-Based Partitioning)**을 예로 들어보겠다.
해시 기반 호리즌탈 파티셔닝
해시 함수(Hash Function)를 사용하여 데이터를 분할하는 방식이다. 예를 들어, user_id를 입력값으로 받아 0 또는 1을 출력하는 해시 함수를 사용한다고 가정하자.
Subscription_0 (user_id, channel_id, alarm, membership)
Subscription_1 (user_id, channel_id, alarm, membership)
- 해시 함수의 출력이 0이면 Subscription_0 테이블에 저장
- 해시 함수의 출력이 1이면 Subscription_1 테이블에 저장
이렇게 하면 기존 테이블과 동일한 스키마를 가진 여러 개의 테이블로 데이터를 분산 저장할 수 있다. 이를 **파티션 키(Partition Key)**를 기준으로 데이터가 나뉘는 방식이라 한다.
예시:
- 특정 사용자가 구독한 채널 정보를 조회하려면 파티션 키인 user_id를 기준으로 해시 함수 결과에 따라 해당 테이블에서만 조회하면 된다.
- 반대로 특정 채널을 구독한 모든 사용자를 조회하려면 모든 파티션 테이블을 조회해야 한다.
중요한 고려 사항
- 파티션 키 선택: 가장 자주 사용되는 조회 패턴을 기준으로 파티션 키를 선택하는 것이 중요하다.
- 데이터 균등 분배: 해시 함수는 데이터를 균등하게 분배할 수 있도록 설계해야 한다. 특정 파티션에만 데이터가 몰리면 성능 저하가 발생할 수 있다.
단점: 파티션 확장 어려움
해시 기반 호리즌탈 파티셔닝은 운영 중에 새로운 파티션을 추가하는 것이 어렵다. 예를 들어, 처음에 Subscription_0, Subscription_1로 나누었다면 이후에 Subscription_2, Subscription_3을 추가하기 어렵다.
따라서 처음 파티셔닝 설계 시 미래의 데이터 증가를 고려하여 파티션 개수를 신중하게 결정해야 한다.
결론
파티셔닝은 대규모 데이터베이스의 성능을 최적화하는 중요한 기술이다.
- 버티컬 파티셔닝은 컬럼을 기준으로 데이터를 나누어 I/O 부하를 줄이고 성능을 향상시킨다.
- 호리즌탈 파티셔닝은 로우를 기준으로 데이터를 나누어 대용량 테이블의 읽기/쓰기 성능을 향상시킨다.
적절한 파티셔닝 전략을 선택하고, 데이터 특성과 사용 패턴을 고려한 파티션 키 설정이 중요하다. 파티셔닝은 잘 설계된 경우 대규모 시스템에서 필수적인 성능 향상 기법이 될 수 있다.
+ 결론
파티셔닝은 가상 개념이 아니라 실제로 데이터베이스의 물리적 구조에 영향을 주는 기법입니다. 이를 좀 더 구체적으로 설명하자면, 파티셔닝은 다음 두 가지 측면에서 물리적으로 구현됩니다:
🎯 1. 물리적인 데이터 분할 (Physical Data Split)
파티셔닝을 적용하면 테이블 자체가 여러 물리적인 파일이나 스토리지 단위로 분할됩니다. 각 파티션은 독립적인 테이블 파일처럼 저장되며, 데이터베이스 시스템이 이를 자동으로 관리합니다.
예를 들어:
- 테이블을 호리즌탈 파티셔닝하면, 각 파티션은 독립된 데이터 파일로 생성됩니다.
- 파일 시스템 상에서 table_part_0, table_part_1 같은 형태로 물리적으로 나눠질 수 있습니다.
📌 DBMS가 파티션을 인식하고 관리함
파티셔닝을 적용하면 사용자는 하나의 테이블처럼 조회하지만, 내부적으로 DBMS는 필요한 파티션에만 접근하여 데이터를 효율적으로 처리합니다.
예시:
SELECT * FROM Subscription WHERE user_id = 123;
위 쿼리를 실행할 때 DBMS는 user_id를 기준으로 어느 파티션에 저장되어 있는지 판단하여 해당 파티션에만 접근합니다. 다른 파티션은 전혀 건드리지 않으므로 불필요한 데이터 검색을 줄여 성능을 최적화할 수 있습니다.
🎯 2. 파티션 키와 해시 함수 (Partition Key & Hash Function)
파티셔닝이 물리적이라면, 파티션 키와 해시 함수는 논리적인 규칙입니다.
- 파티션 키: 데이터를 어느 파티션에 저장할지 결정하는 기준이 되는 컬럼입니다.
- 해시 함수: 파티션 키 값을 입력받아 해당 값이 어떤 파티션으로 가야 할지를 계산하는 함수입니다.
예를 들어, user_id가 파티션 키일 때, 다음과 같은 해시 함수가 있다고 가정해봅시다:
hash(user_id) % 4
이 함수는 user_id 값을 4개의 파티션 중 하나로 매핑합니다.
- user_id = 123이라면 hash(123) % 4 = 3 → 파티션 3으로 저장
- user_id = 456이라면 hash(456) % 4 = 2 → 파티션 2로 저장
이 과정은 DBMS가 내부적으로 처리하며, 개발자는 파티션의 복잡한 물리적 구조를 직접 관리할 필요가 없습니다.
📚 가상 개념과 물리적 개념의 차이
구분 설명 예시
가상 개념 | 논리적 파티션 또는 뷰(View)처럼 보이지만 물리적 분할이 없음 | 특정 조건에 따라 테이블을 나눈 가상 뷰 |
물리적 개념 | 테이블이 실제로 여러 파일로 나뉘고 스토리지에 따로 저장됨 | 호리즌탈 파티셔닝, 버티컬 파티셔닝 |
💡 정리: 파티셔닝은 물리적 개념이다!
파티셔닝은 단순히 논리적인 분류 방식이 아니라 데이터베이스 시스템에서 실제로 테이블을 물리적으로 분할하여 저장하고 관리하는 방식입니다. 다만, 사용자 입장에서는 여전히 하나의 테이블처럼 쿼리할 수 있기 때문에 가상처럼 보일 수 있지만, 내부적으로는 물리적인 구조에 영향을 줍니다.
'데이터베이스' 카테고리의 다른 글
[운영] 반정규화(Denormalization)를 활용한 성능 최적화: 실무 경험과 해결 방안 (0) | 2025.03.11 |
---|---|
[DB] Replication이란? (2) | 2025.01.05 |
[DB] Replication, 데이터베이스 복제와 고가용성 개념 정리 (0) | 2025.01.05 |
[DB] Sharding과 Horizontal Partitioning의 차이점 및 개념 정리 (0) | 2025.01.05 |