Int range partitioning
- Introduced in GitLab 16.8.
설명
Int range partitioning은 정수 열을 기반으로 큰 테이블을 더 작고 관리하기 쉬운 조각으로 나누는 기술입니다. 이는 특히 행의 수가 많은 테이블에 대해 유용하며, 쿼리 성능을 크게 향상시키고, 저장 요구 사항을 줄이고, 유지 관리 작업을 간소화하는 데 도움이 될 수 있습니다. 이러한 종류의 분할이 잘 작동하려면 대부분의 쿼리가 특정 int 범위에서 데이터에 액세스해야 합니다.
이를 더 자세히 살펴보면 간소화된 merge_request_diff_files
스키마를 상상해 보겠습니다:
CREATE TABLE merge_request_diff_files (
merge_request_diff_id INT NOT NULL,
relative_order INT NOT NULL,
PRIMARY KEY (merge_request_diff_id, relative_order));
이제 UI의 일반적인 쿼리가 특정 int 범위에서 데이터를 표시할 것이라고 상상해 보겠습니다:
SELECT *
FROM merge_request_diff_files
WHERE merge_request_diff_id > 1 AND merge_request_diff_id < 10
LIMIT 100
테이블이 merge_request_diff_id
열에 대해 분할되었으면 기본 테이블은 다음과 같을 것입니다:
CREATE TABLE merge_request_diff_files (
merge_request_diff_id INT NOT NULL,
relative_order INT NOT NULL,
PRIMARY KEY (merge_request_diff_id, relative_order))
PARTITION BY RANGE(merge_request_diff_id);
그리고 해당 테이블의 분할 디렉터리이 다음과 같을 수 있습니다:
merge_request_diff_files_1 FOR VALUES FROM (1) TO (20)
merge_request_diff_files_20 FOR VALUES FROM (20) TO (40)
merge_request_diff_files_40 FOR VALUES FROM (40) TO (60)
각 분할은 별도의 물리적 테이블이며, 기본 merge_request_diff_files
테이블과 동일한 구조를 가지지만 지정된 범위 내에 있는 행 데이터만 포함합니다. 예를 들어, 분할 merge_request_diff_files_1
에는 merge_request_diff_id
열이 1
이상이고 20
미만인 행이 포함됩니다.
이제 이전 예제 쿼리를 다시 살펴보면 데이터베이스가 WHERE
를 사용하여 모든 일치하는 행이 merge_request_diff_files_1
분할에 있는 것으로 인식할 수 있습니다. 모든 분할의 모든 데이터를 검색하는 대신에 대부분의 데이터 양이 크게 줄어들 수 있습니다.
예
단계 1: 분할 복사본 생성 (릴리스 N)
첫 번째 단계는 원본 테이블의 분할된 복사본을 만들기 위해 마이그레이션을 추가하는 것입니다. 이 마이그레이션은 원본 테이블의 데이터를 기반으로 적절한 분할을 만들고 원본 테이블에서의 쓰기 작업을 분할된 복사본으로 동기화하는 트리거를 설치합니다.
merge_request_diff_commits
테이블을 merge_request_diff_id
열을 기준으로 분할하는 예제 마이그레이션은 다음과 같습니다:
class PartitionMergeRequestDiffCommits < Gitlab::Database::Migration[2.1]
include Gitlab::Database::PartitioningMigrationHelpers
disable_ddl_transaction!
def up
partition_table_by_int_range(
'merge_request_diff_commits',
'merge_request_diff_id',
partition_size: 10_000_000,
primary_key: %w[merge_request_diff_id relative_order]
)
end
def down
drop_partitioned_table_for('merge_request_diff_commits')
end
end
이 작업이 실행된 후에 원본 테이블에서의 모든 삽입, 업데이트 또는 삭제는 새 테이블에서도 복제됩니다. 업데이트와 삭제의 경우 해당 행이 분할된 테이블에 존재하는 경우에만 작업이 영향을 미칩니다.
단계 2: 분할 복사본 채우기 (릴리스 N)
두 번째 단계는 배포 후 마이그레이션을 추가하여 기존 테이블의 데이터를 분할된 복사본으로 백필하는 배치 작업을 예약하는 것입니다.
위 예제를 계속하면, 해당 마이그레이션은 다음과 같을 것입니다:
class BackfillPartitionMergeRequestDiffCommits < Gitlab::Database::Migration[2.2]
include Gitlab::Database::PartitioningMigrationHelpers
milestone '16.10'
disable_ddl_transaction!
restrict_gitlab_migration gitlab_schema: :gitlab_main
def up
enqueue_partitioning_data_migration :merge_request_diff_commits
end
def down
cleanup_partitioning_data_migration :merge_request_diff_commits
end
end
이 단계는 내부적으로 BATCH_SIZE 및 SUB_BATCH_SIZE가 각각 50,000
및 2,500
인 배치된 백그라운드 마이그레이션을 예약합니다. 자세한 내용은 Batched Background migrations guide를 참조하세요.
단계 3: 백필 후 정리 (릴리스 N+1)
이 단계는 (2) 단계를 포함하는 릴리스 이후에 최소한 하나의 릴리스에서 발생해야 합니다. 이것은 Self-Managed 설치에서 배경 마이그레이션이 올바르게 실행되도록 충분한 시간을 제공합니다. 이 단계에서는 배경 마이그레이션 후 정리를 하는 다른 배포 후 마이그레이션을 추가합니다. 이에는 남아 있는 작업을 실행하도록 강제하는 것 및 삭제되거나 실패한 작업으로 인해 놓칠 수 있는 데이터를 복사하는 것이 포함됩니다.
한번 더 예제를 계속하면, 해당 마이그레이션은 다음과 같을 것입니다:
class CleanupPartitionMergeRequestDiffCommitsBackfill < Gitlab::Database::Migration[2.1]
include Gitlab::Database::PartitioningMigrationHelpers
disable_ddl_transaction!
restrict_gitlab_migration gitlab_schema: :gitlab_main
def up
finalize_backfilling_partitioned_table :merge_request_diff_commits
end
def down
# no op
end
end
이 마이그레이션이 완료된 후에 원본 테이블과 분할된 테이블은 동일한 데이터를 포함해야 합니다. 원본 테이블에 설치된 트리거는 데이터가 앞으로도 동기화됨을 보장합니다.
단계 4: 분할된 테이블과 비분할 테이블 교체 (릴리스 N+1)
이 단계는 비분할 테이블을 분할된 복사본으로 대체합니다. 이 작업은 다른 마이그레이션 단계가 모두 성공적으로 완료된 후에만 사용해야 합니다.
이 방법의 몇 가지 제한 사항은 이전, 또는 동안, 교체 마이그레이션을 처리해야 합니다:
- 보조 인덱스 및 외래 키는 자동으로 분할된 테이블에 재생성되지 않습니다.
- 일부 유형의 제약 조건(고유 및 제외)은 색인에 의존하는데, 해당 색인이 존재하지 않으므로 분할된 테이블에 자동으로 재생성되지 않습니다.
- 비분할 테이블을 참조하는 외래 키는 분할된 테이블을 참조하도록 업데이트되어야 합니다. 이것은 PostgreSQL 11에서 지원되지 않습니다.
- 비분할 테이블을 참조하는 뷰는 자동으로 분할된 테이블을 참조하도록 업데이트되지 않습니다.
# frozen_string_literal: true
class SwapPartitionMergeRequestDiffCommits < 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
이 마이그레이션이 완료된 후:
- 분할된 테이블이 비분할(원본) 테이블을 대체합니다.
- 이전에 생성된 동기화 트리거가 삭제됩니다.
이제 분할된 테이블은 애플리케이션에서 사용할 준비가 되었습니다.