Status | Authors | Coach | DRIs | Owning Stage | Created |
---|---|---|---|---|---|
proposed | - |
- 동기: GitLab.com 안정성 및 성능
- 예시
- GitLab.com의 문제가 되는 테이블들
- 목표: GitLab.com의 모든 물리적 테이블의 크기는 색인을 포함하여 100GB 미만이어야 함
- 솔루션
- 목표
- 담당자
데이터베이스 확장성: GitLab.com의 디스크 테이블 크기 제한을 100GB 미만으로 설정
이 문서는 GitLab.com의 테이블 크기를 줄이고 제한하기 위한 제안입니다. 특정 임계값으로 테이블 크기를 제한함으로써 가능한 목표치를 설정합니다. 이는 데이터베이스의 중점과 의사 결정을 이끄는 지표로 활용됩니다. GitLab.com이 성장함에 따라, 우리는 지속적으로 어떤 테이블들이 수정되어야 하는지 재평가하여, 위반을 방지하거나 해결할 필요가 있습니다.
이는 엄격한 규칙이 아니라, 테이블을 분리하거나 크기를 줄이는 데 노력이 필요함을 강하게 암시하는 것입니다.
이 문서는 데이터베이스 샤딩 설계안과 맥락을 함께 읽는 것이 의도됩니다. 여기에 제안된 것은 우리가 저장 요구 사항을 줄이고 데이터 모델링을 개선하기 위한 “debloating 단계”의 일부로 생각됩니다. 파티셔닝은 표준 도구 세트의 일부입니다. 가능한 경우, 우리는 이미 파티셔닝을 데이터의 접근 차원에 따라 물리적 테이블 크기를 크게 줄일 수 있는 해결책으로 활용할 수 있습니다. 둘 다 분해(데이터베이스 사용이 이미 최적화되어 있음)와 샤딩(데이터베이스가 확인된 데이터 액세스 차원을 따라 이미 파티셔닝되어 있음)과 같은 노력을 준비하는 데 도움이 됩니다.
동기: GitLab.com 안정성 및 성능
GitLab.com의 대형 테이블은 운영 및 개발 양쪽에 중대한 문제입니다. 다음과 같은 여러 가지 문제를 일으킵니다.
- 쿼리 시간 및 따라서 전반적인 애플리케이션 성능에 영향을 미칩니다.
- 테이블 유지 관리가 훨씬 더 많은 비용이 듭니다. GitLab.com에서 Vacuum 활동은 큰 문제가 되었는데, 대형 테이블의 처리와 Vacuum 실행이 완료되기까지 많은 시간이 소요됩니다. 이에는 여러 부정적인 결과가 있으며, 매우 큰 테이블은 데이터베이스의 보다 상관없는 부분에 영향을 줄 가능성이 있으며, 따라서 전반적인 애플리케이션 성능에 영향을 미칠 가능성이 있습니다.
- 대형 테이블에서의 데이터 이전은 구현하기가 훨씬 더 복잡하며 개발 부하가 발생합니다. GitLab.com에서 안정성 문제를 일으키는 가능성이 있으며, 대규모 데이터셋에서 실행하는 데 오랜 시간이 걸립니다.
- 인덱스 크기가 상당히 큽니다. 이는 인덱스의 작은 부분이 메모리에 유지되며 인덱스를 유지하는 데 어렵게 만듭니다(재팩킹 등을 고려해보세요).
- 인덱스 생성 시간이 크게 증가합니다. 2021년에는 B-Tree 생성이 단일 B-Tree 인덱스에 대해 최대 6시간이 소요되는 것을 보았습니다. 이는 우리의 자주 배포하는 능력에 영향을 미치며, Vacuum 관련 문제로 이어져서(지연된 정리) 발생합니다.
- 우리는 문제를 완화하기 위해 많은 인덱스를 추가하는 경향이 있지만, 이로 인해 결과적으로 상당한 오버헤드가 발생하고 쿼리 플래너를 혼란스럽게 할 수 있으며, 많은 수의 인덱스는 설계 문제의 징후입니다.
예시
가장 두드러진 예로, ci_builds
테이블은 2021년 6월 기준으로 1.5TB이며 관련된 31개의 인덱스는 총 1TB에 이릅니다. 이 테이블의 디스크 크기는 2.5TB입니다. 현재 이것은 한 달에 300GB씩 증가합니다. 연말까지 5TB에 가까워질 것으로 보입니다.
다음 예시는 매우 큰 테이블이 종종 GitLab.com의 사건의 근본 원인으로 작용한다는 것을 보여줍니다.
- Vacuum 활동의 빈도가 낮고 긴 기간은 CI 대기열의 쿼리 성능 저하를 반복적으로 유발했습니다.
-
ci_builds
와 같은 대형 테이블에서 인덱스 작성 시에 바쁜 시간대에 1.5시간에서 6시간이 걸립니다. 이 프로세스는 배포를 차단하여, 마이그레이션이 동기적으로 실행되는 동안 우리의 자주 배포하는 능력이 감소합니다. - 대규모 인덱스 생성은 데이터베이스 기본에 활동 폭주를 일으킬 수 있습니다:
-
merge_request_diff_commits
테이블에서: 높은 네트워크 포화를 유발했습니다. - 주말 정기적인 재인덱싱 활동: 증가하는 WAL 대기열을 유발합니다(복구 목표에 영향을 줍니다).
-
notes
테이블: 유지 관리 용도로 GIN 삼자 인덱스를 다시 생성하는 것은 거의 불가능해졌으며, 첫 번째 시도에서 12시간 후에 기타 Vacuum 작업을 차단하며 중단해야했습니다.
-
GitLab.com의 문제가 되는 테이블들
이것은 2021년 6월 중순 기준으로 GitLab.com의 총 테이블 크기(인덱스 크기 포함)별 TOP30 테이블을 보여줍니다. table_size, index_size
는 실제 데이터 및 관련 인덱스의 디스크 크기입니다. percentage_of_total_database_size
는 총 테이블 크기와 데이터베이스 크기의 비율을 표시합니다.
우리는 1TB 이상인 매우 큰 테이블과 매우 큰 인덱스를 가진 테이블을 현재 볼 수 있습니다.
다른 관찰 결과로는 매우 많은 인덱스를 가진 테이블들이 있고, 총 인덱스 크기가 저장된 데이터보다 상당히 큰 경우가 있습니다. 예를 들어 deployments
는 24개의 인덱스에 걸쳐 추가 123GB의 인덱스 데이터와 함께 30GB의 크기입니다.
Table | Total size | Table size | Index size | Index count | Percentage of total database size |
---|---|---|---|---|---|
ci_builds
| 2975 GB | 1551 GB | 941 GB | 30 | 22.7 |
merge_request_diff_commits
| 1890 GB | 1454 GB | 414 GB | 2 | 14.4 |
ci_build_trace_sections
| 1123 GB | 542 GB | 581 GB | 3 | 8.6 |
notes
| 748 GB | 390 GB | 332 GB | 13 | 5.7 |
merge_request_diff_files
| 575 GB | 481 GB | 88 GB | 1 | 4.4 |
events
| 441 GB | 95 GB | 346 GB | 12 | 3.4 |
ci_job_artifacts
| 397 GB | 187 GB | 210 GB | 10 | 3.0 |
ci_pipelines
| 266 GB | 66 GB | 200 GB | 23 | 2.0 |
taggings
| 238 GB | 60 GB | 179 GB | 5 | 1.8 |
ci_builds_metadata
| 237 GB | 88 GB | 149 GB | 5 | 1.8 |
issues
| 219 GB | 47 GB | 150 GB | 28 | 1.7 |
web_hook_logs_202103
| 186 GB | 122 GB | 8416 MB | 3 | 1.4 |
ci_stages
| 182 GB | 58 GB | 124 GB | 6 | 1.4 |
web_hook_logs_202105
| 180 GB | 115 GB | 7868 MB | 3 | 1.4 |
merge_requests
| 176 GB | 44 GB | 125 GB | 36 | 1.3 |
web_hook_logs_202104
| 176 GB | 115 GB | 7472 MB | 3 | 1.3 |
web_hook_logs_202101
| 169 GB | 112 GB | 7231 MB | 3 | 1.3 |
web_hook_logs_202102
| 167 GB | 111 GB | 7106 MB | 3 | 1.3 |
sent_notifications
| 166 GB | 88 GB | 79 GB | 3 | 1.3 |
web_hook_logs_202011
| 163 GB | 113 GB | 7125 MB | 3 | 1.2 |
push_event_payloads
| 162 GB | 114 GB | 48 GB | 1 | 1.2 |
web_hook_logs_202012
| 159 GB | 106 GB | 6771 MB | 3 | 1.2 |
web_hook_logs_202106
| 156 GB | 101 GB | 6752 MB | 3 | 1.2 |
deployments
| 155 GB | 30 GB | 125 GB | 24 | 1.2 |
web_hook_logs_202010
| 136 GB | 98 GB | 6116 MB | 3 | 1.0 |
web_hook_logs_202009
| 114 GB | 82 GB | 5168 MB | 3 | 0.9 |
security_findings
| 109 GB | 21 GB | 88 GB | 8 | 0.8 |
web_hook_logs_202008
| 92 GB | 66 GB | 3983 MB | 3 | 0.7 |
resource_label_events
| 66 GB | 47 GB | 19 GB | 6 | 0.5 |
merge_request_diffs
| 63 GB | 39 GB | 22 GB | 5 | 0.5 |
목표: GitLab.com의 모든 물리적 테이블의 크기는 색인을 포함하여 100GB 미만이어야 함
운영 안정성을 유지하고 향상시키며 개발 부담을 줄이기 위해 GitLab.com의 물리적 테이블 크기를 100GB 미만으로 지정합니다(색인을 포함함). 이에는 다음과 같은 많은 이점이 있습니다:
- 개선된 쿼리 성능 및 더 안정적인 쿼리 계획
- Vacuum 실행 시간을 크게 줄이고 건강한 상태를 유지하기 위해 Vacuum 실행 빈도를 높임 - 데이터베이스 프라이머리에 부담을 줄임
- 인덱스 생성 시간이 크게 단축됨(인덱스 당 읽어야 하는 데이터가 현저히 줄어듦)
- 인덱스가 더 작아져 효율적으로 관리되고 메모리에 더 잘 맞음
- 데이터 마이그레이션이 이해하기 쉽고 구현 및 실행하는 데 시간이 덜 걸림
이 목표는 실용적입니다: 테이블 크기는 기능 사용, 코드 변경 및 기타 요소에 따라 변하기 때문에 일정한 해결책을 항상 찾을 수는 없습니다. 그러나 이는 허용되며 주로 GitLab.com 상황을 통제하기 위해 노력합니다. 노력을 GitLab.com 상황에 맞추고 자주 재평가합니다.
시간이 지남에 따라 특정한 상황에서 일정한 최대 물리적 테이블 크기로 이어지는 변경사항이 있을 수 있지만, 이것이 반드시 그렇지는 않습니다. 예를 들어 테이블을 정적 파티션으로 분할하는 해시 파티셔닝을 고려해보십시오. 시간이 지남에 따라 데이터가 증가하면 개별 파티션도 크기가 커지고 결국 임계 크기에 도달할 수 있습니다. 우리는 일정한 테이블 크기를 얻기 위해 노력합니다만, 이러한 특성이 없는 더 간단한 해결책을 제공하고 일정 기간 동안 상황을 개선하는 것 역시 허용됩니다.
그러므로 리팩터링 후 물리적 테이블의 목표 크기는 상황에 따라 다르며 이에 대한 엄격한 규칙은 없습니다. 물리적 테이블이 100GB의 임계값에 다시 도달할 때까지 과거 데이터 성장과 예측을 고려하는 것이 좋습니다. 이를 통해 어떤 솔루션이 특정 기간 동안 얼마나 지속될 것으로 예상되는지 이해할 수 있습니다.
솔루션
테이블 크기를 줄이기 위한 표준 솔루션이 없습니다 - 많은 솔루션이 있습니다!
- 유지 기간: 불필요한 데이터를 삭제, 예를 들어 오래된 불필요한 레코드의 유효 기간이 만료됩니다.
- STI 제거: 여전히 single-table inheritance를 몇 군데에서 사용 중이며, 이는 안티 패턴으로 간주됩니다. 이를 재설계하여 데이터를 여러 테이블로 분할할 수 있습니다.
- 인덱스 최적화: 불필요한 인덱스 삭제하고 겹치는 인덱스를 가능한 경우 통합합니다.
- 데이터 유형 최적화: 데이터 유형 결정 검토하고 가능한 경우 데이터 유형을 최적화합니다(예: enum 열에 text 대신 integer 사용)
- 파티셔닝: 공통 액세스 차원이 있는 경우 파티션화 스키마 적용
- 정규화: 관계형 모델링 검토하고 정규화 기술을 적용하여 중복 데이터를 제거합니다
- 수직 테이블 분할: 열 사용법 검토 및 테이블을 수직으로 분할
- 외부화: 데이터베이스 외부로 대량의 데이터 유형 이동. 예를 들어, JSON 문서의 경우 필터링에 사용되지 않을 때 데이터베이스 외부에 더 잘 저장할 수 있습니다(예: 객체 리포지터리).
정규화와 같은 솔루션의 경우 이것은 교환권입니다: 비정규화된 모델은 적절하게 사용되는 경우 쿼리 속도를 높일 수 있지만 테이블 크기를 희생해야 합니다. 모델을 정규화하거나 테이블을 분할하거나 데이터를 외부화할 때 성능에 미치는 영향을 이해하고 성능에 크게 영향을 미치지 않는 테이블 크기를 줄이는 솔루션을 찾기 위해 노력합니다.
노력 예시
일부 예는 아래에서 찾을 수 있으며, 더 많은 예는 Database efficiency 에픽 아래에서 조직화되어 있습니다.
ci_builds
의 인덱스 수를 줄이기merge_request_diff_commits
에서 커미터 및 작성자 세부정보 정규화 및 중복 제거ci_build_trace_sections
의 유지 기간 전략- 오래된 CI 작업 메타데이터를 하드 삭제하는 워커 구현](https://gitlab.com/gitlab-org/gitlab/-/issues/215646)
-
merge_request_diff_files
이 < 100GB 목표를 위반함 (에픽)
목표
~group::database
의 에픽은 이를 도달하고 필요한 변경 사항을 식별하여 제시하기 위한 결정을 추진합니다. 이러한 변경 사항은 주로 해당 데이터를 소유하고 사용하는 stage 그룹에 의해 주도되며, ~group::database
는 이를 지원합니다.
담당자
해당 테이블에 대한 해결책을 식별하는 것은 GitLab 데이터베이스 팀 및 해당 stage 그룹에 의해 주도됩니다.
역할 | 담당자 |
---|---|
작성자 | Andreas Brandl |
엔지니어링 리더 | Craig Gomes |