InfoGrab DocsInfoGrab Docs

데이터베이스 테이블 파티셔닝

요약

아래에서 답을 찾지 못한 질문이 있다면 이 이슈를 확인하고 질문을 추가하세요. 테이블 파티셔닝은 테이블 데이터를 하나의 큰 테이블처럼 동작하는 더 작은 물리적 테이블로 분할할 수 있는 강력한 데이터베이스 기능입니다. 데이터베이스가 모든 SQL 기능을 그대로 제공하면서도 검색 범위에서 많은 데이터를 저렴하게 제거할 수 있어 쿼리 성능이 크게 향상될 수 있습니다.

아래에서 답을 찾지 못한 질문이 있다면 이 이슈를 확인하고 질문을 추가하세요. @gitlab-org/database-team/triage 태그를 달면 최대한 빨리 답변을 드립니다. Slack에서 답변을 받은 경우, 향후 이 문서를 업데이트할 수 있도록 이슈에도 내용을 기록해 두세요.

테이블 파티셔닝은 테이블 데이터를 하나의 큰 테이블처럼 동작하는 더 작은 물리적 테이블로 분할할 수 있는 강력한 데이터베이스 기능입니다. 파티셔닝을 염두에 두고 애플리케이션을 설계하면 다음과 같은 여러 이점을 얻을 수 있습니다:

  • 데이터베이스가 모든 SQL 기능을 그대로 제공하면서도 검색 범위에서 많은 데이터를 저렴하게 제거할 수 있어 쿼리 성능이 크게 향상될 수 있습니다.

  • 전체 파티션을 삭제하면 데이터베이스에 미치는 영향을 최소화하면서 대량 삭제를 수행할 수 있습니다. 이는 보존 기간을 벗어난 데이터를 주기적으로 삭제해야 하는 기능에 자연스럽게 맞습니다.

  • VACUUM 및 인덱스 재구성과 같은 관리 작업을 하나의 대형 테이블 전체가 아닌 개별 파티션에 대해 실행할 수 있습니다.

안타깝게도 모든 모델이 파티셔닝 방식에 적합한 것은 아니며, 잘못 구현하면 심각한 문제가 발생할 수 있습니다. 또한 테이블은 생성 시에만 파티셔닝할 수 있어 사용 중인 데이터베이스에 파티셔닝을 적용하는 것은 간단하지 않습니다. 백엔드 개발자가 기존 테이블을 파티셔닝할 수 있도록 마이그레이션 도구 모음이 제공되지만, 마이그레이션 과정은 여러 릴리즈에 걸쳐 여러 단계로 나뉘어 상당히 복잡합니다. 파티셔닝의 제한 사항과 관련 마이그레이션의 특성상, 이 기능을 활용하기 전에 파티셔닝이 사용 사례에 적합한지 충분히 이해해야 합니다.

파티셔닝 마이그레이션 헬퍼는 원본 테이블의 파티셔닝된 복사본을 생성하고, 트리거와 백그라운드 마이그레이션의 조합을 사용하여 새 테이블로 데이터를 복사하는 방식으로 동작합니다. 원본 테이블 스키마 변경은 파티셔닝 마이그레이션과 병행하여 진행할 수 있지만, 마이그레이션이 작동하는 기반 메커니즘이 손상되지 않도록 주의해야 합니다. 예를 들어, 파티셔닝 중인 테이블에 칼럼이 추가되면 파티셔닝된 테이블과 트리거 정의 모두 그에 맞게 업데이트해야 합니다.

파티셔닝 사용 시점 결정#

파티셔닝을 올바르게 적용하면 매우 유용할 수 있지만, 테이블의 데이터와 워크로드가 파티셔닝 방식에 자연스럽게 맞는지 먼저 파악하는 것이 중요합니다. 파티셔닝이 특정 문제에 적합한지 결정하기 위해 다음 사항을 파악하세요:

  • 테이블 파티셔닝. 테이블은 파티션 키를 기준으로 파티셔닝됩니다. 파티션 키는 파티션 간에 데이터를 어떻게 분할할지를 결정하는 칼럼 또는 칼럼 집합입니다. 데이터베이스는 데이터를 읽거나 쓸 때 파티션 키를 사용하여 어떤 파티션에 접근해야 하는지 결정합니다. 파티션 키는 해당 테이블에 접근하는 거의 모든 쿼리의 WHERE 절에 포함될 칼럼이어야 합니다.

  • 데이터 분할 방식. 데이터베이스가 파티션 간에 데이터를 분할하는 데 사용하는 전략은 무엇인가요?

복합 기본 키가 있는 파티셔닝된 테이블을 사용하는 Rails 모델#

PostgreSQL은 파티셔닝된 테이블에서 기본 키를 포함한 모든 고유 제약 조건에 파티션 키가 포함되도록 요구합니다. 테이블이 partition_id 또는 created_at과 같은 칼럼으로 파티셔닝되면, 데이터베이스 수준의 기본 키는 예를 들어 (id, partition_id)와 같은 복합 키가 됩니다.

Rails는 복합 기본 키를 지원합니다. 그러나 복합 키가 PostgreSQL 파티셔닝 요건으로 인해서만 존재하고, id가 여전히 애플리케이션 수준의 행 식별자인 경우, ActiveRecord는 올바른 동작을 자동으로 추론하지 않습니다. 명시적 선언이 없으면, ActiveRecord는 기본 키를 ["id", "partition_id"]로 처리하여 여러 작업에서 잘못된 결과를 반환합니다:

작업 self.primary_key = :id 없을 때의 동작
Model.find(integer) ActiveRecord::RecordNotFound 발생
record.id 정수 대신 [id, partition_id] 배열 반환
record.id == integer 항상 false
to_param / URL 헬퍼 잘못된 경로 세그먼트 생성, 예: "42_100"
as_json["id"] / API 응답 id를 정수 대신 배열로 직렬화

이를 방지하려면 모델에 기본 키를 명시적으로 설정하세요:

class MyModel < ApplicationRecord
  self.primary_key = :id
end

이렇게 하면 ActiveRecord가 레코드 조회에 id만 사용하도록 지시하면서, 데이터베이스는 파티셔닝 목적으로 복합 기본 키를 여전히 적용합니다.

self.primary_key = :id를 설정하면 ActiveRecord 동작이 수정되지만, 쿼리에서 파티션 프루닝이 보장되지는 않습니다. PostgreSQL은 쿼리의 WHERE 절에 파티션 키가 포함된 경우에만 파티션을 프루닝할 수 있습니다. 성능에 민감한 모든 쿼리가 파티션 키 칼럼으로 필터링되도록 하세요. 그렇지 않으면 PostgreSQL이 모든 파티션을 스캔합니다.

id가 파티션 내에서만 고유한 경우#

위 패턴은 id가 단일 시퀀스에서 생성되는 경우처럼 모든 파티션에 걸쳐 전역적으로 고유할 때 충분합니다. 이 경우 id만으로 UPDATEDELETE를 수행해도 올바른 행에 도달합니다.

id가 파티션 내에서만 고유하고 전역적으로는 고유하지 않은 경우, id만으로 필터링된 UPDATE 또는 DELETE는 해당 행을 찾기 위해 모든 파티션을 스캔해야 합니다. 이 경우 query_constraints도 두 칼럼과 함께 선언하여 ActiveRecord가 쓰기 작업의 WHERE 절에 파티션 키를 포함하도록 하세요:

class MyModel < ApplicationRecord
  self.primary_key = :id
  query_constraints :id, :partition_id
end

query_constraintsprimary_key로 구동되는 SELECT 조회에는 영향을 미치지 않습니다. UPDATEDELETE 구문의 WHERE 절에만 나열된 칼럼을 추가하여 PostgreSQL이 쓰기 시 파티션을 프루닝할 수 있도록 합니다.

이 가이드는 PostgreSQL 파티셔닝 요건으로 인해 복합 기본 키가 존재하고 id가 여전히 논리적인 애플리케이션 수준 식별자인 테이블에만 적용됩니다. 모든 복합 기본 키 시나리오에 대한 일반적인 조언이 아닙니다.

적합한 파티셔닝 전략 결정#

사용 가능한 파티셔닝 전략은 date range, int range, hash, list입니다.

데이터베이스 테이블 파티셔닝

GitLab v19.2
원문 보기

요약

아래에서 답을 찾지 못한 질문이 있다면 이 이슈를 확인하고 질문을 추가하세요. 테이블 파티셔닝은 테이블 데이터를 하나의 큰 테이블처럼 동작하는 더 작은 물리적 테이블로 분할할 수 있는 강력한 데이터베이스 기능입니다. 데이터베이스가 모든 SQL 기능을 그대로 제공하면서도 검색 범위에서 많은 데이터를 저렴하게 제거할 수 있어 쿼리 성능이 크게 향상될 수 있습니다.

아래에서 답을 찾지 못한 질문이 있다면 이 이슈를 확인하고 질문을 추가하세요. @gitlab-org/database-team/triage 태그를 달면 최대한 빨리 답변을 드립니다. Slack에서 답변을 받은 경우, 향후 이 문서를 업데이트할 수 있도록 이슈에도 내용을 기록해 두세요.

테이블 파티셔닝은 테이블 데이터를 하나의 큰 테이블처럼 동작하는 더 작은 물리적 테이블로 분할할 수 있는 강력한 데이터베이스 기능입니다. 파티셔닝을 염두에 두고 애플리케이션을 설계하면 다음과 같은 여러 이점을 얻을 수 있습니다:

  • 데이터베이스가 모든 SQL 기능을 그대로 제공하면서도 검색 범위에서 많은 데이터를 저렴하게 제거할 수 있어 쿼리 성능이 크게 향상될 수 있습니다.

  • 전체 파티션을 삭제하면 데이터베이스에 미치는 영향을 최소화하면서 대량 삭제를 수행할 수 있습니다. 이는 보존 기간을 벗어난 데이터를 주기적으로 삭제해야 하는 기능에 자연스럽게 맞습니다.

  • VACUUM 및 인덱스 재구성과 같은 관리 작업을 하나의 대형 테이블 전체가 아닌 개별 파티션에 대해 실행할 수 있습니다.

안타깝게도 모든 모델이 파티셔닝 방식에 적합한 것은 아니며, 잘못 구현하면 심각한 문제가 발생할 수 있습니다. 또한 테이블은 생성 시에만 파티셔닝할 수 있어 사용 중인 데이터베이스에 파티셔닝을 적용하는 것은 간단하지 않습니다. 백엔드 개발자가 기존 테이블을 파티셔닝할 수 있도록 마이그레이션 도구 모음이 제공되지만, 마이그레이션 과정은 여러 릴리즈에 걸쳐 여러 단계로 나뉘어 상당히 복잡합니다. 파티셔닝의 제한 사항과 관련 마이그레이션의 특성상, 이 기능을 활용하기 전에 파티셔닝이 사용 사례에 적합한지 충분히 이해해야 합니다.

파티셔닝 마이그레이션 헬퍼는 원본 테이블의 파티셔닝된 복사본을 생성하고, 트리거와 백그라운드 마이그레이션의 조합을 사용하여 새 테이블로 데이터를 복사하는 방식으로 동작합니다. 원본 테이블 스키마 변경은 파티셔닝 마이그레이션과 병행하여 진행할 수 있지만, 마이그레이션이 작동하는 기반 메커니즘이 손상되지 않도록 주의해야 합니다. 예를 들어, 파티셔닝 중인 테이블에 칼럼이 추가되면 파티셔닝된 테이블과 트리거 정의 모두 그에 맞게 업데이트해야 합니다.

파티셔닝 사용 시점 결정#

파티셔닝을 올바르게 적용하면 매우 유용할 수 있지만, 테이블의 데이터와 워크로드가 파티셔닝 방식에 자연스럽게 맞는지 먼저 파악하는 것이 중요합니다. 파티셔닝이 특정 문제에 적합한지 결정하기 위해 다음 사항을 파악하세요:

  • 테이블 파티셔닝. 테이블은 파티션 키를 기준으로 파티셔닝됩니다. 파티션 키는 파티션 간에 데이터를 어떻게 분할할지를 결정하는 칼럼 또는 칼럼 집합입니다. 데이터베이스는 데이터를 읽거나 쓸 때 파티션 키를 사용하여 어떤 파티션에 접근해야 하는지 결정합니다. 파티션 키는 해당 테이블에 접근하는 거의 모든 쿼리의 WHERE 절에 포함될 칼럼이어야 합니다.

  • 데이터 분할 방식. 데이터베이스가 파티션 간에 데이터를 분할하는 데 사용하는 전략은 무엇인가요?

복합 기본 키가 있는 파티셔닝된 테이블을 사용하는 Rails 모델#

PostgreSQL은 파티셔닝된 테이블에서 기본 키를 포함한 모든 고유 제약 조건에 파티션 키가 포함되도록 요구합니다. 테이블이 partition_id 또는 created_at과 같은 칼럼으로 파티셔닝되면, 데이터베이스 수준의 기본 키는 예를 들어 (id, partition_id)와 같은 복합 키가 됩니다.

Rails는 복합 기본 키를 지원합니다. 그러나 복합 키가 PostgreSQL 파티셔닝 요건으로 인해서만 존재하고, id가 여전히 애플리케이션 수준의 행 식별자인 경우, ActiveRecord는 올바른 동작을 자동으로 추론하지 않습니다. 명시적 선언이 없으면, ActiveRecord는 기본 키를 ["id", "partition_id"]로 처리하여 여러 작업에서 잘못된 결과를 반환합니다:

작업 self.primary_key = :id 없을 때의 동작
Model.find(integer) ActiveRecord::RecordNotFound 발생
record.id 정수 대신 [id, partition_id] 배열 반환
record.id == integer 항상 false
to_param / URL 헬퍼 잘못된 경로 세그먼트 생성, 예: "42_100"
as_json["id"] / API 응답 id를 정수 대신 배열로 직렬화

이를 방지하려면 모델에 기본 키를 명시적으로 설정하세요:

class MyModel < ApplicationRecord
  self.primary_key = :id
end

이렇게 하면 ActiveRecord가 레코드 조회에 id만 사용하도록 지시하면서, 데이터베이스는 파티셔닝 목적으로 복합 기본 키를 여전히 적용합니다.

self.primary_key = :id를 설정하면 ActiveRecord 동작이 수정되지만, 쿼리에서 파티션 프루닝이 보장되지는 않습니다. PostgreSQL은 쿼리의 WHERE 절에 파티션 키가 포함된 경우에만 파티션을 프루닝할 수 있습니다. 성능에 민감한 모든 쿼리가 파티션 키 칼럼으로 필터링되도록 하세요. 그렇지 않으면 PostgreSQL이 모든 파티션을 스캔합니다.

id가 파티션 내에서만 고유한 경우#

위 패턴은 id가 단일 시퀀스에서 생성되는 경우처럼 모든 파티션에 걸쳐 전역적으로 고유할 때 충분합니다. 이 경우 id만으로 UPDATEDELETE를 수행해도 올바른 행에 도달합니다.

id가 파티션 내에서만 고유하고 전역적으로는 고유하지 않은 경우, id만으로 필터링된 UPDATE 또는 DELETE는 해당 행을 찾기 위해 모든 파티션을 스캔해야 합니다. 이 경우 query_constraints도 두 칼럼과 함께 선언하여 ActiveRecord가 쓰기 작업의 WHERE 절에 파티션 키를 포함하도록 하세요:

class MyModel < ApplicationRecord
  self.primary_key = :id
  query_constraints :id, :partition_id
end

query_constraintsprimary_key로 구동되는 SELECT 조회에는 영향을 미치지 않습니다. UPDATEDELETE 구문의 WHERE 절에만 나열된 칼럼을 추가하여 PostgreSQL이 쓰기 시 파티션을 프루닝할 수 있도록 합니다.

이 가이드는 PostgreSQL 파티셔닝 요건으로 인해 복합 기본 키가 존재하고 id가 여전히 논리적인 애플리케이션 수준 식별자인 테이블에만 적용됩니다. 모든 복합 기본 키 시나리오에 대한 일반적인 조언이 아닙니다.

적합한 파티셔닝 전략 결정#

사용 가능한 파티셔닝 전략은 date range, int range, hash, list입니다.