① 동일 기간의 중복 집계
BAD: 6475.344ms, hit=3, read=218673
동일 기간을 두 번 집계
SELECT s.shop_id
,COALESCE(a.ord_amt, 0) AS ord_amt
,COALESCE(b.ord_cnt, 0) AS ord_cnt
FROM startdbpg.ms_shop_big s
LEFT OUTER JOIN
(
SELECT o1.shop_id
,SUM(o1.ord_amt) AS ord_amt
FROM startdbpg.tr_ord_big o1
WHERE o1.ord_st = 'PKUP'
AND o1.ord_dtm >= '2024-01-01'
AND o1.ord_dtm < '2025-01-01'
GROUP BY o1.shop_id
) a ON a.shop_id = s.shop_id
LEFT OUTER JOIN
(
SELECT o2.shop_id
,COUNT(*) ord_cnt
FROM startdbpg.tr_ord_big o2
WHERE o2.ord_st = 'PKUP'
AND o2.ord_dtm >= '2024-01-01'
AND o2.ord_dtm < '2025-01-01'
GROUP BY o2.shop_id
) b ON b.shop_id = s.shop_id
;
SQL
복사
실행계획 보기
•
같은 기간의 주문 750만 건을 두 번 읽었습니다(인라인 뷰마다 read 약 109,000).
GOOD: 3728.893ms, hit=3, read=109338
한 번 집계해 합계·건수 산출
SELECT s.shop_id
,COALESCE(a.ord_amt, 0) AS ord_amt
,COALESCE(a.ord_cnt, 0) AS ord_cnt
FROM startdbpg.ms_shop_big s
LEFT OUTER JOIN
(
SELECT o1.shop_id
,SUM(o1.ord_amt) AS ord_amt
,COUNT(*) ord_cnt
FROM startdbpg.tr_ord_big o1
WHERE o1.ord_st = 'PKUP'
AND o1.ord_dtm >= '2024-01-01'
AND o1.ord_dtm < '2025-01-01'
GROUP BY o1.shop_id
) a ON a.shop_id = s.shop_id
;
SQL
복사
실행계획 보기
•
한 번 읽으면서 합계와 건수를 함께 계산합니다. 읽은 양이 절반이 되고, 6.5초가 3.7초로 줄었습니다.
② WHERE 조건이 다른 인라인 뷰를 CASE로 통합
BAD: 193.613ms, hit=18270, read=0
결제 유형별 인라인 뷰를 각각 집계
SELECT s.shop_id
,COALESCE(a.card_ord_amt, 0) AS card_ord_amt
,COALESCE(b.cash_ord_amt, 0) AS cash_ord_amt
FROM startdbpg.ms_shop_big s
LEFT OUTER JOIN
(
SELECT o1.shop_id
,SUM(o1.ord_amt) AS card_ord_amt
FROM startdbpg.tr_ord_big o1
WHERE o1.ord_dtm >= '2024-01-01'
AND o1.ord_dtm < '2024-02-01'
AND o1.pay_tp = 'CARD'
GROUP BY o1.shop_id
) a ON a.shop_id = s.shop_id
LEFT OUTER JOIN
(
SELECT o2.shop_id
,SUM(o2.ord_amt) AS cash_ord_amt
FROM startdbpg.tr_ord_big o2
WHERE o2.ord_dtm >= '2024-01-01'
AND o2.ord_dtm < '2024-02-01'
AND o2.pay_tp = 'CASH'
GROUP BY o2.shop_id
) b ON b.shop_id = s.shop_id
;
SQL
복사
실행계획 보기
•
같은 1월 주문을 결제 유형만 바꿔 두 번 읽습니다(인라인 뷰마다 hit 9,134).
GOOD: 169.746ms, hit=9138, read=0
CASE로 결제 유형별 금액을 한 번에 집계
SELECT s.shop_id
,COALESCE(a.card_ord_amt, 0) AS card_ord_amt
,COALESCE(a.cash_ord_amt, 0) AS cash_ord_amt
FROM startdbpg.ms_shop_big s
LEFT OUTER JOIN
(
SELECT o1.shop_id
,SUM(CASE WHEN o1.pay_tp = 'CARD' THEN o1.ord_amt END) AS card_ord_amt
,SUM(CASE WHEN o1.pay_tp = 'CASH' THEN o1.ord_amt END) AS cash_ord_amt
FROM startdbpg.tr_ord_big o1
WHERE o1.ord_dtm >= '2024-01-01'
AND o1.ord_dtm < '2024-02-01'
AND o1.pay_tp IN ('CARD', 'CASH')
GROUP BY o1.shop_id
) a ON a.shop_id = s.shop_id
;
SQL
복사
실행계획 보기
•
한 번 읽고, CASE로 결제 유형별 금액을 나눠 합계합니다.
•
지금은 결제 유형이 CARD·CASH뿐이라 pay_tp IN (...)으로 걸러지는 행이 없지만, 다른 결제 유형이 추가되어도 BAD와 같은 대상만 집계하도록 조건을 둡니다.
•
CASE 계산 횟수를 줄이는 방법도 추가로 고려할 수 있습니다. → [권장:성능]대량 행에 CASE 반복 계산
KEY POINT
•
같은 테이블·같은 기간을 인라인 뷰로 여러 번 집계하면, 같은 데이터를 그 횟수만큼 읽습니다.
•
집계 항목만 다르면 한 번의 GROUP BY에서 함께 계산합니다.
•
조건만 다르면 SUM(CASE WHEN ...)으로 한 번에 나눠 집계합니다.
DEEP DIVE — SQL STARTER for MySQL

