오프셋 페이지네이션 최적화
대규모 데이터셋에서 오프셋 기반 페이지네이션의 성능 문제를 완화하기 위한 인덱스 온리 스캔 최적화 기법을 설명합니다.
많은 REST API 엔드포인트에서는 page URL 파라미터를 사용하여 결과를 페이지네이션하는 오프셋 기반 페이지네이션 을 사용합니다. 오프셋 페이지네이션은 선형으로 확장 되기 때문에, 페이지 번호가 높을수록 데이터베이스 쿼리가 느려집니다. 이는 페이지 번호가 클 경우 데이터베이스 쿼리가 타임아웃될 수 있음을 의미합니다. 이 문제는 주로 서드파티 통합 및 스크립트가 시스템과 상호작용할 때 발생하며, 사용자가 의도적으로 높은 페이지 번호를 방문하는 경우는 드뭅니다. 오프셋 페이지네이션과 관련된 확장성 문제를 해결하는 가장 이상적인 방법은 키셋 페이지네이션 으로 전환하는 것입니다. 그러나 이는 API의 호환성을 깨는 변경을 의미합니다. 임시적인 중간 조치로 Gitlab::Pagination::Offset::PaginationWithIndexOnlyScan 클래스를 사용할 수 있습니다. 이 최적화는 높은 OFFSET 값이 존재할 때 오프셋 페이지네이션 쿼리의 성능을 개선하는 데 특정 상황에서 도움이 될 수 있습니다. 성능 개선이란 쿼리가 향상된 쿼리 타이밍으로 선형 확장을 유지한다는 것을 의미하며, 타임아웃이 발생하더라도 훨씬 더 높은 page 번호에서 발생하게 됩니다. 최적화 사용 요구 사항 # 이 최적화는 ORDER BY , OFFSET , LIMIT 절을 기반으로 레코드를 결정할 때 SELECT * 를 호출하지 않고, 데이터베이스 I/O를 줄이기 위해 인덱스 온리 스캔을 사용하려고 시도합니다. 최적화를 사용하려면 키셋 페이지네이션과 동일한 요구 사항을 충족해야 합니다: ORDER BY 절이 있어야 합니다. ORDER BY 절이 하나의 데이터베이스 칼럼을 고유하게 식별해야 합니다. 올바른 예시, 기본 키 사용: ORDER BY id 잘못된 예시, created_at 은 고유하지 않음: ORDER BY created_at 올바른 예시, 타이 브레이커 가 있음: ORDER BY created_at, id 쿼리가 데이터베이스 인덱스로 잘 커버되어야 합니다. 최적화 클래스 사용 방법 # 최적화 클래스는 ActiveRecord::Relation 객체와 함께 사용할 수 있으며, 결과로 최적화된 kaminari 페이지네이션 ActiveRecord::Relation 객체를 반환합니다. 최적화를 적용할 수 없는 경우에는 원래의 ActiveRecord::Relation 객체가 페이지네이션에 사용됩니다. 기본 사용법: scope = Issue.where(project_id: 1).order(:id) records = Gitlab::Pagination::Offset::PaginationWithIndexOnlyScan.new(scope: scope, page: 5, per_page: 100).paginate_with_kaminari puts records.to_a 최적화는 항상 피처 플래그와 함께 배포해야 하며, 특정 조건이 충족될 때 최적화 사용을 타깃팅할 수도 있습니다. # - Only apply optimization for large page numbe