쿼리 성능 가이드라인
GitLab v19.1이 문서는 SQL 쿼리 최적화 시 따라야 할 다양한 가이드라인을 설명합니다. SQL 쿼리를 최적화할 때는 두 가지 측면에 주의해야 합니다: 쿼리 실행 시간. 쿼리 플랜. 쿼리 성능을 분석할 때, 확인 중인 시간이 콜드 또는 웜 캐시 상태에서의 수치인지 주의하세요.
이 문서는 SQL 쿼리 최적화 시 따라야 할 다양한 가이드라인을 설명합니다.
SQL 쿼리를 최적화할 때는 두 가지 측면에 주의해야 합니다:
-
쿼리 실행 시간. 이는 사용자가 GitLab을 경험하는 방식을 반영하므로 가장 중요합니다.
-
쿼리 플랜. 쿼리 플랜을 최적화하는 것은 쿼리가 시간이 지남에 따라 독립적으로 확장될 수 있도록 하는 데 중요합니다. 쿼리가 저하되기 전에 테이블이 커지더라도 인덱스가 쿼리 성능을 유지해 준다는 사실을 사전에 파악하는 것이 이러한 플랜을 분석하는 이유 중 하나입니다.
쿼리 타이밍 가이드라인#
| 쿼리 유형 | 최대 쿼리 시간 | 비고 |
|---|---|---|
| 일반 쿼리 | 100ms | 엄격한 제한은 아니지만, 쿼리가 이 시간을 초과할 경우 최적화 가능 여부 및 그 이유를 파악하는 데 시간을 투자하는 것이 중요합니다. |
| 마이그레이션 내 쿼리 | 100ms | 이는 전체 마이그레이션 시간과는 다릅니다. |
| 마이그레이션 내 동시 작업 | 5분 | 동시 작업은 데이터베이스를 차단하지 않지만 GitLab 업데이트를 차단합니다. add_concurrent_index, add_concurrent_foreign_key, validate constraint(예: add_text_limit을 통한 텍스트 제한 추가) 등의 작업이 포함됩니다. |
| 포스트 마이그레이션 내 동시 작업 | 20분 | 동시 작업은 데이터베이스를 차단하지 않지만 GitLab 포스트 업데이트 프로세스를 차단합니다. add_concurrent_index, add_concurrent_foreign_key, validate constraint(예: add_text_limit을 통한 텍스트 제한 추가) 등의 작업이 포함됩니다. 인덱스 생성이 20분을 초과하는 경우 비동기 인덱스 생성을 고려하세요. |
| 백그라운드 마이그레이션 | 1s | |
| Service Ping | 1s | 자세한 내용은 Metrics Instrumentation 문서를 참조하세요. |
-
쿼리 성능을 분석할 때, 확인 중인 시간이 콜드 또는 웜 캐시 상태에서의 수치인지 주의하세요. 이 가이드라인은 두 캐시 유형 모두에 적용됩니다.
-
배치 쿼리를 작업할 때는 범위 및 배치 크기를 변경하여 쿼리 타이밍과 캐싱에 어떤 영향을 미치는지 확인하세요.
-
기존 쿼리의 성능이 좋지 않은 경우, 개선하려는 노력을 기울이세요. 너무 복잡하거나 개발이 지연될 경우, 적시에 처리할 수 있도록 후속 작업을 생성하세요. 데이터베이스 리뷰어 또는 메인테이너에게 도움과 지도를 요청할 수 있습니다.
콜드 및 웜 캐시#
쿼리 성능을 평가할 때는 콜드 캐시와 웜 캐시 쿼리의 차이를 이해하는 것이 중요합니다.
쿼리가 처음 실행될 때는 "콜드 캐시" 상태로 실행됩니다. 즉, 디스크에서 읽어야 한다는 뜻입니다. 쿼리를 다시 실행하면 데이터를 캐시, 즉 PostgreSQL이 공유 버퍼(shared buffers)라고 부르는 곳에서 읽을 수 있습니다. 이것이 "웜 캐시" 쿼리입니다.
EXPLAIN 플랜을 분석할 때, EXPLAIN(analyze, buffers)로 실행하여 Buffers 출력을 확인함으로써 타이밍뿐만 아니라 차이를 확인할 수 있습니다. Database Lab은 이러한 옵션을 자동으로 포함합니다.
웜 캐시 쿼리를 실행하는 경우 shared hits만 표시됩니다.
예를 들어 Database Lab을 사용하면:
Shared buffers:
- hits: 36467 (~284.90 MiB) from the buffer pool
- reads: 0 from the OS file cache, including disk I/O
또는 psql의 explain 플랜에서:
Buffers: shared hit=7323
캐시가 콜드 상태인 경우 reads도 표시됩니다.
Database Lab을 사용하면:
Shared buffers:
- hits: 17204 (~134.40 MiB) from the buffer pool
- reads: 15229 (~119.00 MiB) from the OS file cache, including disk I/O
psql에서:
Buffers: shared hit=7202 read=121
느린 목록 뷰 및 API#
GitLab에서는 다양한 필터 및 정렬 옵션이 필요한 필터링된 목록 뷰와 API를 자주 구축합니다. 이러한 모든 옵션은 보통 파인더(finder)에 캡슐화되어 API/GraphQL 인수로 노출됩니다. 다양한 페이지네이션 성능 최적화가 가능하지만, 정렬 및 필터링의 모든 조합을 성능 좋게 만들 방법이 없는 경우가 많습니다. 많은 옵션을 성능 좋게 만들려는 시도는 기본 데이터베이스 성능을 희생시키는 너무 많은 인덱스 추가를 수반할 수 있습니다. 이는 일반적인 사용 사례에 대해서만 정당화되며, 필터 및 정렬의 모든 순열을 성능 좋게 만드는 방법으로 간주해서는 안 됩니다. 실질적으로 이것이 의미하는 바는, 특정 정렬 또는 필터링 옵션이 적용될 때 타임아웃이 발생하는 필터링된 뷰와 API 요청이 있을 가능성이 높다는 것입니다. 특정 필터링/정렬 조합을 가진 특정 고객에게 이점이 되는 경우 팀이 이를 추가하는 것은 허용하지만, 일부 사용자에게는 타임아웃이 발생한다는 점을 수용해야 합니다.