목록 분할

설명

분할하는 테이블에 분할 키 열을 추가하세요. 다음의 제약 조건에 분할 키를 포함하세요.

  • 기본 키.
  • 분할할 테이블을 참조하는 모든 외래 키.
  • 모든 고유 제약 조건.

예제

단계 1 - 분할 키 추가

분할 키 열을 추가하세요. 예를 들어, 레일즈 마이그레이션에서:

class AddPartitionNumberForPartitioning < Gitlab::Database::Migration[2.1]
  enable_lock_retries!

  TABLE_NAME = :table_name
  COLUMN_NAME = :partition_id
  DEFAULT_VALUE = 100

  def change
    add_column(TABLE_NAME, COLUMN_NAME, :bigint, default: 100)
  end
end

단계 2 - 필요한 인덱스 생성

분할 키 열을 포함하여 인덱스를 추가하세요. 예를 들어, 레일즈 마이그레이션에서:

class PrepareIndexesForPartitioning < Gitlab::Database::Migration[2.1]
  disable_ddl_transaction!

  TABLE_NAME = :table_name
  INDEX_NAME = :index_name

  def up
    add_concurrent_index(TABLE_NAME, [:id, :partition_id], unique: true, name: INDEX_NAME)
  end

  def down
    remove_concurrent_index_by_name(TABLE_NAME, INDEX_NAME)
  end
end

단계 3 - 고유 제약 조건 적용

분할 키 열을 포함한 모든 고유 인덱스를 변경하고, 기본 키 인덱스를 포함합니다. 다음 두 단계에 필요한 [primary_key_column, :partition_id]에 대한 고유 인덱스를 추가하실 수 있습니다. 예를 들어, 레일즈 마이그레이션에서:

class PrepareUniqueContraintForPartitioning < Gitlab::Database::Migration[2.1]
  disable_ddl_transaction!

  TABLE_NAME = :table_name
  OLD_UNIQUE_INDEX_NAME = :index_name_unique
  NEW_UNIQUE_INDEX_NAME = :new_index_name

  def up
    add_concurrent_index(TABLE_NAME, [:id, :partition_id], unique: true, name: NEW_UNIQUE_INDEX_NAME)

    remove_concurrent_index_by_name(TABLE_NAME, OLD_UNIQUE_INDEX_NAME)
  end

  def down
    add_concurrent_index(TABLE_NAME, :id, unique: true, name: OLD_UNIQUE_INDEX_NAME)

    remove_concurrent_index_by_name(TABLE_NAME, NEW_UNIQUE_INDEX_NAME)
  end
end

단계 4 - 외래 키 제약 조건 적용

분할 키 열을 포함한 외래 키를 적용하세요. 예를 들어, 레일즈 마이그레이션에서:

class PrepareForeignKeyForPartitioning < Gitlab::Database::Migration[2.1]
  disable_ddl_transaction!

  SOURCE_TABLE_NAME = :source_table_name
  TARGET_TABLE_NAME = :target_table_name
  COLUMN = :foreign_key_id
  TARGET_COLUMN = :id
  FK_NAME = :fk_365d1db505_p
  PARTITION_COLUMN = :partition_id

  def up
    add_concurrent_foreign_key(
      SOURCE_TABLE_NAME,
      TARGET_TABLE_NAME,
      column: [PARTITION_COLUMN, COLUMN],
      target_column: [PARTITION_COLUMN, TARGET_COLUMN],
      validate: false,
      on_update: :cascade,
      name: FK_NAME
    )

    # 이것은 높은 트래픽 테이블을 처리할 때 별도의 추가 마이그레이션에서 수행되어야 합니다
    validate_foreign_key(TABLE_NAME, [PARTITION_COLUMN, COLUMN], name: FK_NAME)
  end

  def down
    with_lock_retries do
      remove_foreign_key_if_exists(SOURCE_TABLE_NAME, name: FK_NAME)
    end
  end
end

… (텍스트가 매우 길어 생략합니다)

단계 7 - 외래 키를 상위 테이블로 재지정

초기 파티션을 참조하는 테이블은 이제 상위 테이블을 가리키도록 업데이트해야 합니다. 이 변경을 하지 않으면 해당 테이블의 레코드는 다음 파티션에 있는 행을 찾을 수 없을 것입니다. 왜냐하면 그들은 초기 파티션에서 그것들을 찾으려고 할 것이기 때문입니다.

단계:

  • 파티션된 테이블에 외래 키를 추가하고 비동기적으로 유효성을 검사하세요, 예시처럼.
  • GitLab.com에서 비동기 검증이 완료된 후 동기적으로 유효성을 검사하세요, 예시처럼.
  • 이전 외래 키를 제거하고 새로운 것을 이전 이름으로 변경하세요, 예시처럼.

단계 8 - 파티션 간 ID 고유성 보장

모든 고유성 제약은 파티션 키를 포함해야 하므로 파티션 간에 중복된 ID를 가질 수 있습니다. 이를 해결하기 위해 데이터베이스만이 ID 값을 설정하고 시퀀스를 사용하여 고유한 값을 생성하도록 강제합니다. 왜냐하면 시퀀스는 고유한 값을 생성하는 것이 보장되기 때문입니다.

예시:

class EnsureIdUniquenessForPCiBuilds < Gitlab::Database::Migration[2.1]
  include Gitlab::Database::PartitioningMigrationHelpers::UniquenessHelpers

  enable_lock_retries!

  TABLE_NAME = :p_ci_builds
  SEQ_NAME = :ci_builds_id_seq

  def up
    ensure_unique_id(TABLE_NAME, seq: SEQ_NAME)
  end

  def down
    revert_ensure_unique_id(TABLE_NAME, seq: SEQ_NAME)
  end
end

단계 9 - 파티션된 테이블 분석 및 새 파티션 생성

자동 진공 데몬은 파티션된 테이블을 처리하지 않습니다. 테이블 계층구조의 통계를 최신 상태로 유지하기 위해 주기적으로 수동으로 ANALYZE를 실행해야 합니다.

Ci::Partitionablepartitioned: true 옵션을 사용하여 구현된 모델은 기본적으로 주간 기준으로 분석합니다. 이를 가능하게 하고 새로운 파티션을 생성하려면 모델을 PostgreSQL 초기화 파일에 등록해야 합니다.

단계 10 - 애플리케이션 업데이트하여 파티션된 테이블 사용

이제 상위 테이블이 준비되었으므로 애플리케이션을 사용하도록 업데이트할 수 있습니다:

class Model < ApplicationRecord
  self.table_name = :partitioned_table
end

모델에 따라 변경 관리 이슈를 사용하는 것이 더 안전할 수 있습니다.