This page contains information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned on this page are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc.
Status Authors Coach DRIs Owning Stage Created
proposed -

데이터베이스 확장성: GitLab.com의 디스크 테이블 크기 제한은 100GB 미만

이 문서는 GitLab.com에서 테이블 크기를 줄이고 제한하는 방향으로 작업하기 위한 제안서입니다. 우리는 일정한 한계로 테이블 크기를 제한함으로써 측정 가능한 목표(measurable target)를 설정합니다. 이는 데이터베이스에 대한 주의를 촉발시키고 의사 결정을 이끌어내는 지표로 사용됩니다. GitLab.com이 성장함에 따라, 우리는 지속적으로 어떤 테이블을 작업해야 하는지 재평가하여 위반을 방지하거나 수정해야 합니다.

이 문서는 엄격한 규칙이 아닌, 오히려 테이블을 분리하거나 크기를 줄이는 작업이 필요하다는 강력한 표시이며 그렇게 읽어야 합니다.

이것은 데이터베이스 샤딩 블루프린트와 함께 읽는 것이 의미가 있으며, 이것은 더 큰 그림을 그립니다. 이곳에서의 제안은 아래 “디블로팅 단계”의 일부로 생각되며, 우리는 저장소 요건을 줄이고 데이터 모델링을 개선하기 위해 노력합니다. 파티셔닝은 표준 도구: 가능한 곳에서 물리적 테이블 크기를 크게 줄이는 해결책으로 이미 사용할 수 있습니다. 이 둘은 분해(데이터베이스 사용이 이미 최적화됨) 및 샤딩(식별된 데이터 액세스 차원을 따라 데이터베이스가 이미 파티션화됨)과 같은 노력을 준비하는 데 도움이 됩니다.

graph LR Fe(Pick feature) --> D D[(Database)] --> De De[Debloating] --> Dc Dc[Decomposition] --> P P[Partitioning] --> S S[Sharding] --> R P --> M M[Microservices] --> R R{Repeat?} --> Fe style De fill:#fca326 style P fill:#fc6d26

동기: GitLab.com의 안정성과 성능

GitLab.com의 대형 테이블은 운영 및 개발 모두에 있어 주요 문제점입니다. 이로 인해 여러 가지 문제가 발생합니다.

  1. 쿼리 시간 및 따라서 전반적인 애플리케이션 성능이 저하됩니다.
  2. 테이블 유지 관리는 상당히 더 많은 비용이 소요됩니다. GitLab.com에서 Vacuum 활동은 큰 문제가 되었는데, 큰 테이블에서는 빈번하지 않게(일일 1회) 처리되고 Vacuum 실행에는 많은 시간이 소요됩니다. 이것은 여러 부정적인 결과를 낳으며 매우 큰 테이블은 데이터베이스의 보이지 않는 부분에 영향을 줄 수도 있어 전반적인 애플리케이션 성능이 저하됩니다.
  3. 대형 테이블에서의 데이터 이관은 구현하기가 훨씬 복잡하며 개발 부담을 초래합니다. 이는 GitLab.com에서 안정성 문제를 일으키고 대형 데이터셋에서 실행하는 데 오랜 시간이 걸릴 수 있습니다.
  4. 인덱스 크기는 상당히 큽니다. 이것은 성능에 직접적인 영향을 미치며 인덱스의 작은 부분을 메모리에 보관하고 인덱스를 유지 관리하기 어렵게 만듭니다(다시 패킹하기).
  5. 인덱스 생성 시간이 상당히 증가합니다 - 2021년에는 단일 B-트리 인덱스를 생성하는 데 최대 6시간이 소요된다고 합니다. 이것은 우리가 자주 배포할 수 있는 능력에 영향을 미치며 Vacuum 관련 문제(지연된 클린업)로 이어집니다.
  6. 우리는 해소하기 위해 많은 인덱스를 추가하지만, 이렇게 하면 결국 상당한 부하를 일으키고 쿼리 플래너를 혼동시킬 수 있으며 많은 수의 인덱스는 설계 문제의 징후입니다.

예시

가장 두드러지게, ci_builds 테이블은 2021년 6월 기준으로 1.5TB의 크기를 가지며 이와 연관된 31개의 인덱스가 있으며 이들의 합은 1TB의 크기를 갖습니다. 이 테이블의 디스크 크기는 전체적으로 2.5TB입니다. 현재, 이 테이블은 매월 300GB씩 성장하고 있습니다. 연말까지 이는 조치를 취하지 않는다면 5TB에 가까워질 것으로 보입니다.

다음 예시는 GitLab.com에서 대형 테이블이 종종 사건의 근본 원인이 되는 것을 나타냅니다.

  1. 빈번하고 긴 실행 Vacuum 활동으로 CI 큐잉의 쿼리 성능 저하가 반복적으로 발생했습니다.
  2. ci_builds와 같은 대형 테이블에서, 인덱스 생성 시간이 바빴던 때에는 1.5시간에서 6시간 사이로 변동되었습니다. 이 프로세스는 마이그레이션이 동기적으로 실행되는 동안 배포를 차단하며 배포 빈도를 낮춥니다.
  3. 대규모 인덱스를 생성하는 것은 기본 데이터베이스에서 활동이 폭발할 수 있습니다.
    1. merge_request_diff_commits 테이블: 네트워크 포화 상태를 일으켰습니다.
    2. 주말에 정기적인 다시 인덱싱 작업: 증가하는 WAL 큐를 유발합니다(회복 목표에 영향을 미침).
    3. ‘notes’ 테이블: 유지 관리를 위해 GIN 트리그램 인덱스를 재생성하는 것은 거의 불가능해졌으며 첫 번째 시도에서 12시간이 지난 후에 중단되어 다른 Vacuum 작업을 차단했습니다.

GitLab.com의 문제가 있는 테이블

2021년 6월 중순 기준으로 GitLab.com의 TOP30 테이블을 해당 테이블의 총 크기(인덱스 크기 포함)로 보여줍니다. table_size, index_size는 실제 데이터와 관련된 인덱스의 디스크 크기를 나타냅니다. percentage_of_total_database_size는 테이블 크기와 데이터베이스 크기의 비율을 표시합니다.

우리는 현재 1TB 이상의 매우 큰 테이블이 있으며, 이러한 테이블은 매우 큰 인덱스를 가지기도 합니다.

다른 관찰 결과로는 인덱스가 많은 테이블도 있으며 총 인덱스 크기가 저장된 데이터보다 큰 경우도 있습니다. 예를 들어, deployments의 크기는 30GB이며 24개의 인덱스에 걸쳐 추가로 123GB의 인덱스 데이터가 있습니다.

테이블 총 크기 테이블 크기 인덱스 크기 인덱스 수 데이터베이스 크기 대비 비율
ci_builds 2975GB 1551GB 941GB 30 22.7
merge_request_diff_commits 1890GB 1454GB 414GB 2 14.4
ci_build_trace_sections 1123GB 542GB 581GB 3 8.6
notes 748GB 390GB 332GB 13 5.7
merge_request_diff_files 575GB 481GB 88GB 1 4.4
events 441GB 95GB 346GB 12 3.4
ci_job_artifacts 397GB 187GB 210GB 10 3.0
ci_pipelines 266GB 66GB 200GB 23 2.0
taggings 238GB 60GB 179GB 5 1.8
ci_builds_metadata 237GB 88GB 149GB 5 1.8
issues 219GB 47GB 150GB 28 1.7
web_hook_logs_202103 186GB 122GB 8416MB 3 1.4
ci_stages 182GB 58GB 124GB 6 1.4
web_hook_logs_202105 180GB 115GB 7868MB 3 1.4
merge_requests 176GB 44GB 125GB 36 1.3
web_hook_logs_202104 176GB 115GB 7472MB 3 1.3
web_hook_logs_202101 169GB 112GB 7231MB 3 1.3
web_hook_logs_202102 167GB 111GB 7106MB 3 1.3
sent_notifications 166GB 88GB 79GB 3 1.3
web_hook_logs_202011 163GB 113GB 7125MB 3 1.2
push_event_payloads 162GB 114GB 48GB 1 1.2
web_hook_logs_202012 159GB 106GB 6771MB 3 1.2
web_hook_logs_202106 156GB 101GB 6752MB 3 1.2
deployments 155GB 30GB 125GB 24 1.2
web_hook_logs_202010 136GB 98GB 6116MB 3 1.0
web_hook_logs_202009 114GB 82GB 5168MB 3 0.9
security_findings 109GB 21GB 88GB 8 0.8
web_hook_logs_202008 92GB 66GB 3983MB 3 0.7
resource_label_events 66GB 47GB 19GB 6 0.5
merge_request_diffs 63GB 39GB 22GB 5 0.5

목표: GitLab.com의 모든 물리적 테이블은 인덱스를 포함하여 100GB 미만이어야 함

참고: PostgreSQL 문맥에서 물리적 테이블은 일반 테이블이거나 파티셔닝된 테이블의 파티션입니다.

운영 안정성을 유지하고 향상시키며 개발 부담을 줄이기 위해 GitLab.com의 물리적 테이블 크기는 100GB 미만을 목표로 합니다 (인덱스 포함). 이에는 다수의 장점이 있습니다:

  1. 쿼리 성능 향상 및 안정적인 쿼리 계획
  2. Vacuum 실행 시간 크게 축소 및 건강한 상태를 유지하기 위한 Vacuum 실행 빈도 증가 - 데이터베이스 주 서버의 부하 감소
  3. 인덱스 생성 시간이 크게 단축됨 (인덱스 당 읽어야 하는 데이터가 훨씬 적음)
  4. 인덱스가 작아서 더 효율적으로 유지보수되고 메모리에 더 적합함
  5. 데이터 마이그레이션이 더 쉬워지고 실행 및 이행하는 데 소요되는 시간이 줄어듦

이 목표는 실용적입니다: 우리는 테이블 크기가 기능 사용, 코드 변경 및 기타 요인에 따라 변하는 것을 이해합니다 - 이는 시간이 지남에 따라 모두 변합니다. 우리가 영구적으로 물리적 테이블 크기를 엄격히 제한할 수 있는 해결책을 항상 찾을 수 있는 것은 아닙니다. 그러나 이는 허용되며, 주로 GitLab.com 상황을 통제하려는 것이 주요 목표입니다. 우리는 노력을 GitLab.com에 적합한 상황에 맞추고 자주 재평가합니다.

시간이 경과함에 따라 상수 최대 물리적 테이블 크기로 이어지는 변경 사항이 있지만, 이런 경우가 반드시 그렇다고 할 필요는 없습니다. 예를 들어 해시 파티셔닝은 테이블을 정적 파티션으로 분할합니다. 시간이 지남에 따라 개별 파티션도 크기가 커지고 결국 다시 임계 크기에 도달할 수 있습니다. 테이블 크기를 일정하게 유지하기 위해 노력하지만, 이 특성을 갖추지는 않지만 상당 기간 동안 상황을 개선하는 더 쉬운 솔루션을 제공할 수 있는 것은 허용됩니다.

따라서 리팩터링 후 물리적 테이블의 목표 크기는 상황에 따라 다르며 이에 대한 엄격한 규칙은 없습니다. 물리적 테이블이 다시 100GB의 임계 크기에 도달할 것으로 예상할 수 있도록 과거 데이터 성장과 예측을 고려하는 것을 제안합니다. 이를 통해 특정 솔루션이 어느 정도의 시간이 지날 때까지 기대될 수 있는지 이해할 수 있습니다.

솔루션

테이블 크기를 줄이기 위한 표준 솔루션이 없습니다 - 다수의 솔루션이 있습니다!

  1. 유지: 불필요한 데이터 삭제, 예를 들어 오래된 필요 없는 레코드 만료
  2. STI 제거: 여전히 몇 군데에서 단일 테이블 상속을 사용하고 있으며, 이는 안티 패턴으로 간주됩니다. 이를 재설계하여 데이터를 여러 테이블로 분할할 수 있습니다.
  3. 인덱스 최적화: 불필요한 인덱스 삭제하고 겹치는 인덱스를 통합하는 것이 가능한 경우
  4. 데이터 유형 최적화: 데이터 유형 결정 검토 및 가능한 경우 데이터 유형 최적화 (예: enum 열에 텍스트 대신 정수 사용)
  5. 파티셔닝: 공통 액세스 차원이 있는 경우 파티셔닝 계획 적용
  6. 정규화: 관계 모델링 검토하고 중복 데이터를 제거하기 위해 정규화 기법 적용
  7. 수직 테이블 분할: 열 사용법 검토하고 테이블을 수직으로 분할
  8. 외부화: 데이터베이스 외부로 대규모 데이터 유형 이동. 예를 들어 서브 필터링에 사용되지 않는 경우 JSON 문서는 데이터베이스 외부, 예를 들어 객체 저장소에 더 적합할 수 있습니다.

참고: 물리적 테이블 크기를 제한하는 것을 목표로 하지만, 성능 유지 또는 개선도 목표로 여기고 있습니다.

정규화와 같은 솔루션의 경우, 이는 트레이드오프입니다: 비정규화된 모델은 적절하게 사용될 때 쿼리를 가속화시킬 수 있지만 테이블 크기에 대가를 치야합니다. 모델을 정규화하고 테이블을 분할하거나 데이터를 외부화할 때, 성능에 미치는 영향을 이해하고 성능에 크게 영향을 미치지 않는 테이블 크기를 줄이는 솔루션을 찾으려고 노력합니다.

노력 예시

아래에는 몇 가지 예시가 있으며, 더 많은 예시는 Epic 데이터베이스 효율성 아래에서 구성되어 있습니다.

  1. ci_builds에서 인덱스 수 감소
  2. merge_request_diff_commits에서 커미터 및 작성자 세부 정보 정규화 및 중복 제거
  3. ci_build_trace_sections의 유지 전략
  4. 오래된 CI 작업 메타데이터를 완전 삭제하는 worker 구현](https://gitlab.com/gitlab-org/gitlab/-/issues/215646)
  5. merge_request_diff_files가 < 100 GB 목표를 위반함 (Epic)

목표

~group::database Epic는 해당 데이터를 소유한 단계 그룹 (및 해당 기능)이 이끌며, ~group::database가 지원하는 결정을 내리고 목표를 확립하고 필요한 변경 사항을 제안하도록 합니다. 해당 변경은 주로 데이터를 소유한 단계 그룹에 의해 주도되어야 하지만 ~group::database가 지원해야 합니다.

누구인가

해당 테이블의 문제 해결책을 찾는 것은 GitLab 데이터베이스 팀과 관련 단계 그룹에 의해 이끌어집니다.

역할 누가?
저자 Andreas Brandl
엔지니어링 리더 Craig Gomes