InfoGrab DocsInfoGrab Docs

날짜 범위 파티셔닝

요약

GitLab 마이그레이션 헬퍼가 가장 잘 지원하는 방식은 날짜 범위 파티셔닝(date-range partitioning)으로, 테이블의 각 파티션이 단일 월의 데이터를 포함합니다. 더 구체적인 예시로, audit_events 테이블 사용을 고려해 보겠습니다.


날짜 범위 파티셔닝#

설명#

GitLab 마이그레이션 헬퍼가 가장 잘 지원하는 방식은 날짜 범위 파티셔닝(date-range partitioning)으로, 테이블의 각 파티션이 단일 월의 데이터를 포함합니다. 이 경우 파티셔닝 키는 타임스탬프 또는 날짜 칼럼이어야 합니다. 이 유형의 파티셔닝이 제대로 작동하려면 대부분의 쿼리가 특정 날짜 범위의 데이터에 접근해야 합니다.

더 구체적인 예시로, audit_events 테이블 사용을 고려해 보겠습니다. 이 테이블은 애플리케이션 데이터베이스에서 파티셔닝된 최초의 테이블입니다. 이 테이블은 애플리케이션에서 발생하는 보안 이벤트의 감사 항목을 추적합니다. 거의 모든 경우에 사용자는 특정 시간대에 발생한 감사 활동을 확인하고자 합니다. 따라서 날짜 범위 파티셔닝은 데이터 접근 방식에 자연스럽게 적합했습니다.

이를 더 자세히 살펴보기 위해, 단순화된 audit_events 스키마를 상상해 보겠습니다:

CREATE TABLE audit_events (
  id SERIAL NOT NULL PRIMARY KEY,
  author_id INT NOT NULL,
  details jsonb NOT NULL,
  created_at timestamptz NOT NULL);

이제 UI의 일반적인 쿼리가 특정 날짜 범위(예: 단일 주)의 데이터를 표시한다고 가정해 보겠습니다:

SELECT *
FROM audit_events
WHERE created_at >= '2020-01-01 00:00:00'
  AND created_at < '2020-01-08 00:00:00'
ORDER BY created_at DESC
LIMIT 100

테이블이 created_at 칼럼으로 파티셔닝되면 기본 테이블은 다음과 같습니다:

CREATE TABLE audit_events (
  id SERIAL NOT NULL,
  author_id INT NOT NULL,
  details jsonb NOT NULL,
  created_at timestamptz NOT NULL,
  PRIMARY KEY (id, created_at))
PARTITION BY RANGE(created_at);

파티셔닝된 테이블의 기본 키는 기본 키 정의의 일부로 파티션 키를 포함해야 합니다.

그리고 테이블에 대한 파티션 목록은 다음과 같을 수 있습니다:

audit_events_202001 FOR VALUES FROM ('2020-01-01') TO ('2020-02-01')
audit_events_202002 FOR VALUES FROM ('2020-02-01') TO ('2020-03-01')
audit_events_202003 FOR VALUES FROM ('2020-03-01') TO ('2020-04-01')

각 파티션은 기본 audit_events 테이블과 동일한 구조를 가진 별도의 물리적 테이블이지만, 파티션 키가 지정된 범위에 속하는 행의 데이터만 포함합니다. 예를 들어, audit_events_202001 파티션은 created_at 칼럼이 2020-01-01 이상이고 2020-02-01 미만인 행을 포함합니다.

이제 이전 예시 쿼리를 다시 살펴보면, 데이터베이스는 WHERE 절을 사용하여 모든 일치하는 행이 audit_events_202001 파티션에 있음을 인식할 수 있습니다. 모든 파티션의 전체 데이터를 검색하는 대신, 적절한 파티션에서 단일 월의 데이터만 검색할 수 있습니다. 대용량 테이블에서 이는 데이터베이스가 접근해야 하는 데이터 양을 크게 줄일 수 있습니다. 그러나 파티셔닝 키를 기반으로 필터링하지 않는 쿼리를 상상해 보겠습니다:

SELECT *
FROM audit_events
WHERE author_id = 123
ORDER BY created_at DESC
LIMIT 100

이 예시에서 데이터베이스는 일치하는 데이터가 어느 파티션에든 존재할 수 있으므로 검색에서 파티션을 제외할 수 없습니다. 따라서 각 파티션을 개별적으로 쿼리하고 행을 단일 결과 집합으로 집계해야 합니다. author_id는 인덱싱되어 있으므로 성능 영향은 허용 가능할 수 있지만, 더 복잡한 쿼리에서는 오버헤드가 상당할 수 있습니다. 파티셔닝은 데이터의 접근 패턴이 파티셔닝 전략을 지원하는 경우에만 활용해야 하며, 그렇지 않으면 성능이 저하됩니다.

시간 범위 파티셔닝 전략#

GitLab은 시간 범위 파티셔닝을 위한 두 가지 전략을 지원합니다:

  • 일별 파티셔닝

  • 월별 파티셔닝

시간 범위 파티셔닝 사용#

모델에서 시간 범위 파티셔닝을 사용하려면 PartitionedTable 모듈을 포함하고 파티션 설정을 구성합니다:

class WebHookLog < ApplicationRecord
  include PartitionedTable

  partitioned_by :created_at, strategy: :monthly, retain_for: 1.month
end

사용 가능한 전략#

일별 전략 (:daily)#

일별 전략은 하루에 하나의 파티션을 생성합니다:

partitioned_by :created_at, strategy: :daily, retain_for: 7.days

월별 전략 (:monthly)#

월별 전략은 한 달에 하나의 파티션을 생성합니다:

partitioned_by :created_at, strategy: :monthly, retain_for: 3.months, analyze_interval: 3.days

구성 옵션#

  • column: 파티셔닝할 칼럼 (필수, 타임스탬프 또는 날짜 칼럼이어야 함)

  • strategy: :daily 또는 :monthly 중 하나 (필수)

  • retain_for: 파티션 보존 기간 (선택 사항)

  • analyze_interval: 새 파티션에서 ANALYZE를 실행하는 빈도 (선택 사항)

세분화된 파티셔닝이 필요한 대용량 테이블에는 :daily를, 일별 파티셔닝이 과도할 수 있는 중간 정도의 데이터 볼륨을 가진 테이블에는 :monthly를 선택합니다.

예시#

1단계: 파티셔닝된 복사본 생성 (릴리즈 N)#

첫 번째 단계는 원본 테이블의 파티셔닝된 복사본을 생성하는 마이그레이션을 추가하는 것입니다. 이 마이그레이션은 원본 테이블의 데이터를 기반으로 적절한 파티션을 생성하고, 원본 테이블에서 파티셔닝된 복사본으로 쓰기를 동기화하는 트리거를 설치합니다.

audit_events 테이블을 created_at 칼럼으로 파티셔닝하는 마이그레이션 예시는 다음과 같습니다:

class PartitionAuditEvents < Gitlab::Database::Migration[2.1]
  include Gitlab::Database::PartitioningMigrationHelpers

  def up
    partition_table_by_date :audit_events, :created_at
  end

  def down
    drop_partitioned_table_for :audit_events
  end
end

다음으로, 임시 파티셔닝된 테이블을 config/initializers/postgres_partitioning.rb에 등록합니다. 이 등록을 통해 파티션 관리자가 트리거가 데이터를 동기화할 때 새 파티션을 생성할 수 있습니다. 예를 들어:

Gitlab::Database::Partitioning.register_tables(
  [
    {
      limit_connection_names: %i[main],
      table_name: 'audit_events_partitioned_table_name',
      partitioned_column: :created_at, strategy: :monthly
    }
  ]
)

이 예시에는 다음이 포함됩니다:

  • table_name: 임시 파티셔닝된 테이블의 이름 (예: audit_events_b8088ecbd2).

  • partitioned_column: 파티셔닝에 사용되는 칼럼.

  • strategy: :daily 또는 :monthly 중 하나.

데이터가 특정 기간 후에 삭제되어야 하더라도, 이 등록에 retain_for를 추가하지 마십시오. 백필(backfill) 중에 retain_for가 설정되면 파티션 관리자가 오래된 파티션을 분리할 수 있으며, 백필이 분리된 파티션에 데이터를 복사하려 할 때 실패할 수 있습니다. 테이블 교체(4단계)가 완료된 후에만 모델에 retain_for를 추가합니다.

테이블 교체(4단계)가 완료되면 이 등록을 제거할 수 있습니다.

마이그레이션이 실행된 후, 원본 테이블의 삽입, 업데이트 또는 삭제 작업은 새 테이블에도 복제됩니다. 업데이트와 삭제의 경우, 해당 행이 파티셔닝된 테이블에 존재하는 경우에만 작업이 적용됩니다.

2단계: 파티셔닝된 복사본 백필 (릴리즈 N)#

두 번째 단계는 원본 테이블에서 파티셔닝된 복사본으로 기존 데이터를 백필하는 백그라운드 job을 스케줄링하는 배포 후 마이그레이션을 추가하는 것입니다.

위의 예시를 계속 이어서, 마이그레이션은 다음과 같습니다:

class BackfillPartitionAuditEvents < Gitlab::Database::Migration[2.1]
  include Gitlab::Database::PartitioningMigrationHelpers

  disable_ddl_transaction!

  restrict_gitlab_migration gitlab_schema: :gitlab_main_org
  MIGRATION = 'BackfillPartitionedAuditEvents'

  def up
    enqueue_partitioning_data_migration :audit_events, MIGRATION
  end

  def down
    cleanup_partitioning_data_migration :audit_events, MIGRATION
  end
end

배치된 백그라운드 마이그레이션은 db/docs/batched_background_migrations/ 하위에서 추적되며 고유한 이름이 필요합니다. lib/gitlab/background_migration/BackfillPartitionedTable의 서브클래스를 생성하고 마이그레이션에서 참조합니다:

class BackfillPartitionedAuditEvents < BackfillPartitionedTable; end

이 단계는 내부적으로 BATCH_SIZE와 SUB_BATCH_SIZE를 각각 50,0002,500으로 설정하여 배치된 백그라운드 마이그레이션을 큐에 넣습니다. 자세한 내용은 배치된 백그라운드 마이그레이션 가이드를 참조하세요.

3단계: 백필 후 정리 (2단계 이후 필수 정지 다음 릴리즈)#

2단계에서 실행된 백그라운드 마이그레이션이 GitLab Self-Managed 인스턴스에서 성공적으로 완료될 수 있도록, 2단계와 3단계 사이에 필수 정지가 발생해야 합니다.

이 단계에서는 백그라운드 마이그레이션 후 정리를 수행하는 또 다른 배포 후 마이그레이션을 추가합니다. 여기에는 남아 있는 job을 강제로 실행하고, 삭제되거나 실패한 job으로 인해 누락될 수 있는 데이터를 복사하는 작업이 포함됩니다.

예시를 계속 이어서, 이 마이그레이션은 다음과 같습니다:

class CleanupPartitionedAuditEventsBackfill < Gitlab::Database::Migration[2.1]
  include Gitlab::Database::PartitioningMigrationHelpers

  disable_ddl_transaction!

  restrict_gitlab_migration gitlab_schema: :gitlab_main_org

  def up
    finalize_backfilling_partitioned_table :audit_events
  end

  def down
    # no op
  end
end

이 마이그레이션이 완료된 후 원본 테이블과 파티셔닝된 테이블은 동일한 데이터를 포함해야 합니다. 원본 테이블에 설치된 트리거는 이후에도 데이터가 동기화된 상태를 유지하도록 보장합니다.

4단계: 파티셔닝된 테이블과 비파티셔닝된 테이블 교체 (릴리즈 N+1)#

이 단계는 비파티셔닝된 테이블을 파티셔닝된 복사본으로 교체합니다. 이 단계는 다른 모든 마이그레이션 단계가 성공적으로 완료된 후에만 사용해야 합니다.

이 방법의 일부 제한 사항은 교체 마이그레이션 이전이나 진행 중에 처리되어야 합니다:

  • 보조 인덱스와 외래 키는 파티셔닝된 테이블에 자동으로 재생성되지 않습니다.

  • 인덱스에 의존하는 일부 유형의 제약 조건(UNIQUE 및 EXCLUDE)은 기반이 되는 인덱스가 없으므로 파티셔닝된 테이블에 자동으로 재생성되지 않습니다.

  • 원본 비파티셔닝된 테이블을 참조하는 외래 키는 파티셔닝된 테이블을 참조하도록 업데이트해야 합니다. 이는 PostgreSQL 11에서는 지원되지 않습니다.

  • 원본 테이블을 참조하는 뷰는 파티셔닝된 테이블을 참조하도록 자동 업데이트되지 않습니다.

# frozen_string_literal: true

class SwapPartitionedAuditEvents < ActiveRecord::Migration[6.0]
  include Gitlab::Database::PartitioningMigrationHelpers

  def up
    replace_with_partitioned_table :audit_events
  end

  def down
    rollback_replace_with_partitioned_table :audit_events
  end
end

이 마이그레이션이 완료된 후:

  • 파티셔닝된 테이블이 비파티셔닝된(원본) 테이블을 대체합니다.

  • 이전에 생성된 동기화 트리거가 삭제됩니다.

이제 파티셔닝된 테이블이 애플리케이션에서 사용할 준비가 되었습니다.

(1단계에서 설명한 대로) config/initializers/postgres_partitioning.rb에 임시 파티셔닝된 테이블을 등록했다면, 교체 후에는 임시 테이블이 더 이상 존재하지 않으므로 해당 등록을 제거합니다.

특정 기간 동안만 데이터를 보존하려면 모델에 retain_for를 추가합니다:

class ProjectDailyStatistic < ApplicationRecord
  include PartitionedTable

  partitioned_by :date, strategy: :monthly, retain_for: 3.months
end

이렇게 하면 파티션 관리자가 오래된 파티션을 자동으로 삭제합니다.

날짜 범위 파티셔닝

GitLab v19.1
원문 보기
요약

GitLab 마이그레이션 헬퍼가 가장 잘 지원하는 방식은 날짜 범위 파티셔닝(date-range partitioning)으로, 테이블의 각 파티션이 단일 월의 데이터를 포함합니다. 더 구체적인 예시로, audit_events 테이블 사용을 고려해 보겠습니다.


날짜 범위 파티셔닝#

설명#

GitLab 마이그레이션 헬퍼가 가장 잘 지원하는 방식은 날짜 범위 파티셔닝(date-range partitioning)으로, 테이블의 각 파티션이 단일 월의 데이터를 포함합니다. 이 경우 파티셔닝 키는 타임스탬프 또는 날짜 칼럼이어야 합니다. 이 유형의 파티셔닝이 제대로 작동하려면 대부분의 쿼리가 특정 날짜 범위의 데이터에 접근해야 합니다.

더 구체적인 예시로, audit_events 테이블 사용을 고려해 보겠습니다. 이 테이블은 애플리케이션 데이터베이스에서 파티셔닝된 최초의 테이블입니다. 이 테이블은 애플리케이션에서 발생하는 보안 이벤트의 감사 항목을 추적합니다. 거의 모든 경우에 사용자는 특정 시간대에 발생한 감사 활동을 확인하고자 합니다. 따라서 날짜 범위 파티셔닝은 데이터 접근 방식에 자연스럽게 적합했습니다.

이를 더 자세히 살펴보기 위해, 단순화된 audit_events 스키마를 상상해 보겠습니다:

CREATE TABLE audit_events (
  id SERIAL NOT NULL PRIMARY KEY,
  author_id INT NOT NULL,
  details jsonb NOT NULL,
  created_at timestamptz NOT NULL);

이제 UI의 일반적인 쿼리가 특정 날짜 범위(예: 단일 주)의 데이터를 표시한다고 가정해 보겠습니다:

SELECT *
FROM audit_events
WHERE created_at >= '2020-01-01 00:00:00'
  AND created_at < '2020-01-08 00:00:00'
ORDER BY created_at DESC
LIMIT 100

테이블이 created_at 칼럼으로 파티셔닝되면 기본 테이블은 다음과 같습니다:

CREATE TABLE audit_events (
  id SERIAL NOT NULL,
  author_id INT NOT NULL,
  details jsonb NOT NULL,
  created_at timestamptz NOT NULL,
  PRIMARY KEY (id, created_at))
PARTITION BY RANGE(created_at);

파티셔닝된 테이블의 기본 키는 기본 키 정의의 일부로 파티션 키를 포함해야 합니다.

그리고 테이블에 대한 파티션 목록은 다음과 같을 수 있습니다:

audit_events_202001 FOR VALUES FROM ('2020-01-01') TO ('2020-02-01')
audit_events_202002 FOR VALUES FROM ('2020-02-01') TO ('2020-03-01')
audit_events_202003 FOR VALUES FROM ('2020-03-01') TO ('2020-04-01')

각 파티션은 기본 audit_events 테이블과 동일한 구조를 가진 별도의 물리적 테이블이지만, 파티션 키가 지정된 범위에 속하는 행의 데이터만 포함합니다. 예를 들어, audit_events_202001 파티션은 created_at 칼럼이 2020-01-01 이상이고 2020-02-01 미만인 행을 포함합니다.

이제 이전 예시 쿼리를 다시 살펴보면, 데이터베이스는 WHERE 절을 사용하여 모든 일치하는 행이 audit_events_202001 파티션에 있음을 인식할 수 있습니다. 모든 파티션의 전체 데이터를 검색하는 대신, 적절한 파티션에서 단일 월의 데이터만 검색할 수 있습니다. 대용량 테이블에서 이는 데이터베이스가 접근해야 하는 데이터 양을 크게 줄일 수 있습니다. 그러나 파티셔닝 키를 기반으로 필터링하지 않는 쿼리를 상상해 보겠습니다:

SELECT *
FROM audit_events
WHERE author_id = 123
ORDER BY created_at DESC
LIMIT 100

이 예시에서 데이터베이스는 일치하는 데이터가 어느 파티션에든 존재할 수 있으므로 검색에서 파티션을 제외할 수 없습니다. 따라서 각 파티션을 개별적으로 쿼리하고 행을 단일 결과 집합으로 집계해야 합니다. author_id는 인덱싱되어 있으므로 성능 영향은 허용 가능할 수 있지만, 더 복잡한 쿼리에서는 오버헤드가 상당할 수 있습니다. 파티셔닝은 데이터의 접근 패턴이 파티셔닝 전략을 지원하는 경우에만 활용해야 하며, 그렇지 않으면 성능이 저하됩니다.

시간 범위 파티셔닝 전략#

GitLab은 시간 범위 파티셔닝을 위한 두 가지 전략을 지원합니다:

  • 일별 파티셔닝

  • 월별 파티셔닝

시간 범위 파티셔닝 사용#

모델에서 시간 범위 파티셔닝을 사용하려면 PartitionedTable 모듈을 포함하고 파티션 설정을 구성합니다:

class WebHookLog < ApplicationRecord
  include PartitionedTable

  partitioned_by :created_at, strategy: :monthly, retain_for: 1.month
end

사용 가능한 전략#

일별 전략 (:daily)#

일별 전략은 하루에 하나의 파티션을 생성합니다:

partitioned_by :created_at, strategy: :daily, retain_for: 7.days

월별 전략 (:monthly)#

월별 전략은 한 달에 하나의 파티션을 생성합니다:

partitioned_by :created_at, strategy: :monthly, retain_for: 3.months, analyze_interval: 3.days

구성 옵션#

  • column: 파티셔닝할 칼럼 (필수, 타임스탬프 또는 날짜 칼럼이어야 함)

  • strategy: :daily 또는 :monthly 중 하나 (필수)

  • retain_for: 파티션 보존 기간 (선택 사항)

  • analyze_interval: 새 파티션에서 ANALYZE를 실행하는 빈도 (선택 사항)

세분화된 파티셔닝이 필요한 대용량 테이블에는 :daily를, 일별 파티셔닝이 과도할 수 있는 중간 정도의 데이터 볼륨을 가진 테이블에는 :monthly를 선택합니다.

예시#

1단계: 파티셔닝된 복사본 생성 (릴리즈 N)#

첫 번째 단계는 원본 테이블의 파티셔닝된 복사본을 생성하는 마이그레이션을 추가하는 것입니다. 이 마이그레이션은 원본 테이블의 데이터를 기반으로 적절한 파티션을 생성하고, 원본 테이블에서 파티셔닝된 복사본으로 쓰기를 동기화하는 트리거를 설치합니다.

audit_events 테이블을 created_at 칼럼으로 파티셔닝하는 마이그레이션 예시는 다음과 같습니다:

class PartitionAuditEvents < Gitlab::Database::Migration[2.1]
  include Gitlab::Database::PartitioningMigrationHelpers

  def up
    partition_table_by_date :audit_events, :created_at
  end

  def down
    drop_partitioned_table_for :audit_events
  end
end

다음으로, 임시 파티셔닝된 테이블을 config/initializers/postgres_partitioning.rb에 등록합니다. 이 등록을 통해 파티션 관리자가 트리거가 데이터를 동기화할 때 새 파티션을 생성할 수 있습니다. 예를 들어:

Gitlab::Database::Partitioning.register_tables(
  [
    {
      limit_connection_names: %i[main],
      table_name: 'audit_events_partitioned_table_name',
      partitioned_column: :created_at, strategy: :monthly
    }
  ]
)

이 예시에는 다음이 포함됩니다:

  • table_name: 임시 파티셔닝된 테이블의 이름 (예: audit_events_b8088ecbd2).

  • partitioned_column: 파티셔닝에 사용되는 칼럼.

  • strategy: :daily 또는 :monthly 중 하나.

데이터가 특정 기간 후에 삭제되어야 하더라도, 이 등록에 retain_for를 추가하지 마십시오. 백필(backfill) 중에 retain_for가 설정되면 파티션 관리자가 오래된 파티션을 분리할 수 있으며, 백필이 분리된 파티션에 데이터를 복사하려 할 때 실패할 수 있습니다. 테이블 교체(4단계)가 완료된 후에만 모델에 retain_for를 추가합니다.

테이블 교체(4단계)가 완료되면 이 등록을 제거할 수 있습니다.

마이그레이션이 실행된 후, 원본 테이블의 삽입, 업데이트 또는 삭제 작업은 새 테이블에도 복제됩니다. 업데이트와 삭제의 경우, 해당 행이 파티셔닝된 테이블에 존재하는 경우에만 작업이 적용됩니다.

2단계: 파티셔닝된 복사본 백필 (릴리즈 N)#

두 번째 단계는 원본 테이블에서 파티셔닝된 복사본으로 기존 데이터를 백필하는 백그라운드 job을 스케줄링하는 배포 후 마이그레이션을 추가하는 것입니다.

위의 예시를 계속 이어서, 마이그레이션은 다음과 같습니다:

class BackfillPartitionAuditEvents < Gitlab::Database::Migration[2.1]
  include Gitlab::Database::PartitioningMigrationHelpers

  disable_ddl_transaction!

  restrict_gitlab_migration gitlab_schema: :gitlab_main_org
  MIGRATION = 'BackfillPartitionedAuditEvents'

  def up
    enqueue_partitioning_data_migration :audit_events, MIGRATION
  end

  def down
    cleanup_partitioning_data_migration :audit_events, MIGRATION
  end
end

배치된 백그라운드 마이그레이션은 db/docs/batched_background_migrations/ 하위에서 추적되며 고유한 이름이 필요합니다. lib/gitlab/background_migration/BackfillPartitionedTable의 서브클래스를 생성하고 마이그레이션에서 참조합니다:

class BackfillPartitionedAuditEvents < BackfillPartitionedTable; end

이 단계는 내부적으로 BATCH_SIZE와 SUB_BATCH_SIZE를 각각 50,0002,500으로 설정하여 배치된 백그라운드 마이그레이션을 큐에 넣습니다. 자세한 내용은 배치된 백그라운드 마이그레이션 가이드를 참조하세요.

3단계: 백필 후 정리 (2단계 이후 필수 정지 다음 릴리즈)#

2단계에서 실행된 백그라운드 마이그레이션이 GitLab Self-Managed 인스턴스에서 성공적으로 완료될 수 있도록, 2단계와 3단계 사이에 필수 정지가 발생해야 합니다.

이 단계에서는 백그라운드 마이그레이션 후 정리를 수행하는 또 다른 배포 후 마이그레이션을 추가합니다. 여기에는 남아 있는 job을 강제로 실행하고, 삭제되거나 실패한 job으로 인해 누락될 수 있는 데이터를 복사하는 작업이 포함됩니다.

예시를 계속 이어서, 이 마이그레이션은 다음과 같습니다:

class CleanupPartitionedAuditEventsBackfill < Gitlab::Database::Migration[2.1]
  include Gitlab::Database::PartitioningMigrationHelpers

  disable_ddl_transaction!

  restrict_gitlab_migration gitlab_schema: :gitlab_main_org

  def up
    finalize_backfilling_partitioned_table :audit_events
  end

  def down
    # no op
  end
end

이 마이그레이션이 완료된 후 원본 테이블과 파티셔닝된 테이블은 동일한 데이터를 포함해야 합니다. 원본 테이블에 설치된 트리거는 이후에도 데이터가 동기화된 상태를 유지하도록 보장합니다.

4단계: 파티셔닝된 테이블과 비파티셔닝된 테이블 교체 (릴리즈 N+1)#

이 단계는 비파티셔닝된 테이블을 파티셔닝된 복사본으로 교체합니다. 이 단계는 다른 모든 마이그레이션 단계가 성공적으로 완료된 후에만 사용해야 합니다.

이 방법의 일부 제한 사항은 교체 마이그레이션 이전이나 진행 중에 처리되어야 합니다:

  • 보조 인덱스와 외래 키는 파티셔닝된 테이블에 자동으로 재생성되지 않습니다.

  • 인덱스에 의존하는 일부 유형의 제약 조건(UNIQUE 및 EXCLUDE)은 기반이 되는 인덱스가 없으므로 파티셔닝된 테이블에 자동으로 재생성되지 않습니다.

  • 원본 비파티셔닝된 테이블을 참조하는 외래 키는 파티셔닝된 테이블을 참조하도록 업데이트해야 합니다. 이는 PostgreSQL 11에서는 지원되지 않습니다.

  • 원본 테이블을 참조하는 뷰는 파티셔닝된 테이블을 참조하도록 자동 업데이트되지 않습니다.

# frozen_string_literal: true

class SwapPartitionedAuditEvents < ActiveRecord::Migration[6.0]
  include Gitlab::Database::PartitioningMigrationHelpers

  def up
    replace_with_partitioned_table :audit_events
  end

  def down
    rollback_replace_with_partitioned_table :audit_events
  end
end

이 마이그레이션이 완료된 후:

  • 파티셔닝된 테이블이 비파티셔닝된(원본) 테이블을 대체합니다.

  • 이전에 생성된 동기화 트리거가 삭제됩니다.

이제 파티셔닝된 테이블이 애플리케이션에서 사용할 준비가 되었습니다.

(1단계에서 설명한 대로) config/initializers/postgres_partitioning.rb에 임시 파티셔닝된 테이블을 등록했다면, 교체 후에는 임시 테이블이 더 이상 존재하지 않으므로 해당 등록을 제거합니다.

특정 기간 동안만 데이터를 보존하려면 모델에 retain_for를 추가합니다:

class ProjectDailyStatistic < ApplicationRecord
  include PartitionedTable

  partitioned_by :date, strategy: :monthly, retain_for: 3.months
end

이렇게 하면 파티션 관리자가 오래된 파티션을 자동으로 삭제합니다.