DB

[DB][MySQL] ROW_NUMBER()와 WITH (CTE)를 사용할 때 성능 차이

오선지♬ 2025. 5. 26. 19:37
728x90
반응형

✅ 시나리오 예제: 게시판 페이징

데이터 상황

  • 게시글 테이블 T_BD에 10만 건의 데이터가 있다고 가정
  • 게시글에는 공지사항(상단 고정) 여부, 등록일, 제목, 본문 등의 컬럼이 있음
  • 목표: 특정 게시글(BD_CD)이 몇 페이지에 있는지 계산

① 인라인 뷰 (서브쿼리) 방식

sql
복사편집
SELECT * 
FROM ( 
	SELECT 
    	BD_CD
        , BD_TITLE
        , ROW_NUMBER() OVER (ORDER BY NOTI_YN DESC, INS_DT DESC) AS RN 
    FROM T_BD 
    WHERE 
    	USE_YN = TRUE 
) R 
WHERE 
	R.BD_CD = 'BD12345';
 

🟢 장점

  • BD_CD 조건이 바깥쪽에서 바로 필터링되므로 불필요한 전체 정렬을 피할 수 있음
  • 옵티마이저가 WHERE R.BD_CD = ? 조건을 활용해 필요한 범위만 계산하게 최적화 가능

② WITH (CTE) 방식

sql
WITH RANKED_BD AS (
	SELECT 
    	BD_CD
        , BD_TITLE
        , ROW_NUMBER() OVER (ORDER BY NOTI_YN DESC, INS_DT DESC) AS RN 
    FROM T_BD 
    WHERE 
    	USE_YN = TRUE 
) 
SELECT * 
FROM RANKED_BD 
WHERE 
	BD_CD = 'BD12345';
 

🔴 잠재적 단점

  • 일부 DB에서는 WITH 절의 쿼리를 하나의 독립된 결과셋으로 먼저 완전히 생성한 뒤 → 거기서 다시 조건 필터링 수행
  • 즉, BD_CD 하나 찾기 위해서도 전체 10만 건 정렬이 발생할 수 있음

🔬 실제 실행계획 차이 (예시)

항목 인라인 뷰 방식 WITH (CTE) 방식
정렬 대상 조건 반영 후 부분 정렬 (필터+정렬) 전체 정렬 후 BD_CD 필터
실행 계획 필터 → 정렬 정렬 → 필터
I/O 필요한 만큼만 조회 전 행 스캔 및 정렬
속도 (대량 데이터 시) 빠름 상대적으로 느림
 

💡 결론 요약

상황 추천 방식 이유
단순 페이징, BD_CD 위치 계산 인라인 뷰 조건이 나중에 적용되며 최적화 용이
CTE 결과를 여러 번 재사용 (e.g. JOIN 반복) WITH (CTE) 재사용성이 필요할 때 유리
복잡한 로직 분리, 가독성 중요 WITH (CTE) 쿼리 유지보수에 유리
성능 우선 & 단일 조회 목적 인라인 뷰 옵티마이저가 더 잘 최적화함
728x90
반응형