📘데이터 조회시 인덱싱 처리하여 속도 향상
WHERE 절이나 ORDER BY, JOIN, GROUP BY 등에 자주 사용되는 컬럼에 효과적WHERE 조건에 맞는 레코드를 모두 풀 스캔
메모리에서 정렬 수행
거기서 LIMIT으로 자름
→ 데이터가 많을수록 속도 급격히 저하
@Index(columnList = "a,b")는 WHERE a=? AND b=?에 유리하지만 WHERE b=?에는 효과 없음인덱싱 처리 할 쿼리문
/**
*삭제되지 않았으며, 주어진 날짜 이후에 열리는 콘서트들을 공연일과 ID 기준으로 오름차순 정렬하여 조회
* @param now 공연일 기준 필터 날짜 (이 날짜 이후의 공연만 조회됨)
* @param pageable 페이징 및 페이지 크기 설정
* @return 조건에 맞는 콘서트 목록을 포함하는 페이지 객체
*/
@Query("""
SELECT c FROM Concert c
WHERE c.isDeleted = false AND c.performanceDate >= :now
ORDER BY c.performanceDate ASC, c.id ASC
""")
Page<Concert> findUpcomingConcerts(@Param("now") LocalDate now, Pageable pageable);
엔티티에 index 추가
@Entity
@Table(name = "concerts", indexes = {
@Index(
name = "idx_isDeleted_performanceDate",
columnList = "isDeleted, performanceDate ASC, id ASC"
)}
)
@Getter
public class Concert extends BaseEntity
name = "idx_isDeleted_performanceDate" → 생성될 DB 인덱스 이름 (명시적으로 부여함, 가독성 및 관리 용이)columnList = "isDeleted, performanceDate ASC, id ASC" → 인덱스를 구성할 컬럼들의 순서 및 정렬 방향 지정isDeleted: Soft Delete 필터
WHERE isDeleted = false 조건을 사용performanceDate: 공연 날짜 기준 필터 및 정렬
WHERE performanceDate >= :now + ORDER BY performanceDate ASCid: 정렬의 유일성 확보
performanceDate가 동일한 레코드가 많을 경우 ORDER BY id ASC로 안정적인 정렬 보장id ASC를 포함하면 쿼리에서 정렬 최적화 가능isDeleted = false
isDeleted = true로 비활성화)WHERE 필터의 진입점i % 5 != 0으로 80%는 false (= 조회 대상), 20%는 trueperformanceDate >= :now
>= 조건이기 때문에 Range Scan이 가능i % 100 == 0일 때만 미래 날짜 (랜덤 0~29일 뒤)해당 구조의 의미
isDeleted = false인 건: 약 80만 건performanceDate >= :now인 건: 약 8,000건 정도 (0.8%)| 인덱스 적용 전 | 인덱스 적용 후 |
|---|---|
| 595ms | 106ms |
| 520ms | 116ms |
| 512ms | 102ms |
| 519ms | 103ms |
| 548ms | 118ms |