1. 콘텐츠 목록 조회
contents 테이블에 Partial 복합 인덱스 2개 추가
적용한 인덱스
-- 평균 평점 정렬
CREATE INDEX idx_contents_active_rating
ON contents (average_rating DESC, id)
WHERE deleted_at IS NULL;
-- 최신순 정렬
CREATE INDEX idx_contents_active_created
ON contents (created_at DESC, id)
WHERE deleted_at IS NULL;
WHERE deleted_at IS NULL Partial Index로 삭제된 행 제외 → 인덱스 크기 축소 + 쓰기 오버헤드 최소화
id 후미 컬럼으로 커서 기반 페이지네이션의 동점 해결
EXPLAIN ANALYZE 비교
Before (인덱스 없음)
Seq Scan on contents → Sort → Limit
- Full Table Scan 후 메모리에서 정렬 수행
After (인덱스 적용)
Limit (cost=0.28..2.61 rows=21)
-> Index Scan using idx_contents_active_rating on contents
(actual time=0.040..0.063 rows=21 loops=1)
Planning Time: 2.584 ms
Execution Time: 0.085 ms
- Index Scan으로 정렬 순서대로 21개만 읽고 즉시 반환
- Scan + Sort 모두 제거
k6 부하 테스트 결과 비교
응답 시간
| 지표 |
Before |
After |
변화율 |
| p95 |
215.19ms |
36.58ms |
-83.0% |
| p90 |
127.01ms |
28.91ms |
-77.2% |
| avg |
51.42ms |
16.15ms |
-68.6% |
| med |
18.39ms |
13.43ms |
-27.0% |
| max |
1.46s |
342.99ms |
-76.5% |
처리량
| 지표 |
Before |
After |
변화율 |
| http_reqs |
39,149 |
43,103 |
+10.1% |
| req/s |
127.3 |
140.2 |
+10.1% |
| iterations |
13,016 |
14,334 |
+10.1% |
| 에러율 |
0% |
0% |
동일 |