BAD: 139.620ms, hit=65663
페이징 이전에 상세 조인
SELECT o.ord_no ,o.ord_dtm
,m.mbr_id ,m.nick_nm
,s.shop_id ,s.shop_nm
,c1.base_cd_nm AS ord_st_nm
,c2.base_cd_nm AS pay_tp_nm
FROM startdbpg.tr_ord_big o
LEFT OUTER JOIN startdbpg.ms_mbr_big m
ON (m.mbr_id = o.mbr_id)
LEFT OUTER JOIN startdbpg.ms_shop_big s
ON (s.shop_id = o.shop_id)
LEFT OUTER JOIN startdbpg.cm_base_cd c1
ON (c1.base_cd_dv = 'ord_st' AND c1.base_cd = o.ord_st)
LEFT OUTER JOIN startdbpg.cm_base_cd c2
ON (c2.base_cd_dv = 'pay_tp' AND c2.base_cd = o.pay_tp)
WHERE o.ord_dtm >= '2024-01-01'
AND o.ord_dtm < '2024-02-01'
ORDER BY o.ord_dtm DESC, o.ord_no DESC
LIMIT 100 OFFSET 30000
;
SQL
복사
실행계획 보기
•
301페이지를 보여 주려고, 앞 페이지까지 포함한 30,100건을 회원·매장·코드와 모두 조인한 뒤 앞 30,000건을 버립니다.
•
페이지가 뒤로 갈수록 조인 건수가 계속 늘어납니다.
GOOD: 16.959ms, hit=1275
페이징 후 필요한 행만 조인
SELECT o.ord_no ,o.ord_dtm
,m.mbr_id ,m.nick_nm
,s.shop_id ,s.shop_nm
,c1.base_cd_nm AS ord_st_nm
,c2.base_cd_nm AS pay_tp_nm
FROM (
SELECT o1.ord_no ,o1.ord_dtm ,o1.ord_st ,o1.pay_tp ,o1.mbr_id ,o1.shop_id
FROM startdbpg.tr_ord_big o1
WHERE o1.ord_dtm >= '2024-01-01'
AND o1.ord_dtm < '2024-02-01'
ORDER BY o1.ord_dtm DESC ,o1.ord_no DESC
LIMIT 100 OFFSET 30000
) o
LEFT OUTER JOIN startdbpg.ms_mbr_big m
ON (m.mbr_id = o.mbr_id)
LEFT OUTER JOIN startdbpg.ms_shop_big s
ON (s.shop_id = o.shop_id)
LEFT OUTER JOIN startdbpg.cm_base_cd c1
ON (c1.base_cd_dv = 'ord_st' AND c1.base_cd = o.ord_st)
LEFT OUTER JOIN startdbpg.cm_base_cd c2
ON (c2.base_cd_dv = 'pay_tp' AND c2.base_cd = o.pay_tp)
ORDER BY o.ord_dtm DESC, o.ord_no DESC
;
SQL
복사
실행계획 보기
•
보여 줄 100건만 먼저 고르고, 그 100건만 조인합니다.
•
몇 번째 페이지든 조인은 항상 100건입니다.
KEY POINT
•
페이징 SQL은 페이지에 보여 줄 행만 먼저 고르고, 그다음에 조인합니다.
•
조인한 뒤 페이징하면 OFFSET까지 포함한 행을 모두 조인하므로, 뒤 페이지로 갈수록 느려집니다.
•
안쪽에서 페이징한 뒤에도 바깥에 ORDER BY를 다시 씁니다.
TIP. 먼저 페이징할 수 없는 경우
•
조인 결과로 행이 걸러지거나 늘어나면 먼저 페이징할 수 없습니다. 예를 들어 조인한 테이블의 조건으로 주문을 거르는 INNER JOIN이라면, 페이징 후 조인하면 페이지마다 건수가 모자랍니다.
•
이 방식은 지금처럼 LEFT OUTER JOIN이고, 주문 1건에 1건씩 붙을 때 씁니다.
DEEP DIVE관련 페이지: [권장:성능]페이징 전 스칼라 서브쿼리




