테이블을 여러 번 읽는 것보다는 SUM(CASE)로 한 번 읽는 게 낫습니다([권장:성능]중복 집계 인라인 뷰 (2번 예제 재검토)). 여기서 한 단계 더 나아가, 한 번 읽더라도 CASE 계산 횟수를 줄일 수 있습니다.
BAD: 624.306ms, hit=9134, read=0
전체 주문에 CASE를 반복 적용
SELECT SUM(CASE WHEN EXTRACT(DOW FROM o.ord_dtm) = 0 THEN o.ord_amt END) sun
,SUM(CASE WHEN EXTRACT(DOW FROM o.ord_dtm) = 1 THEN o.ord_amt END) mon
,SUM(CASE WHEN EXTRACT(DOW FROM o.ord_dtm) = 2 THEN o.ord_amt END) tue
,SUM(CASE WHEN EXTRACT(DOW FROM o.ord_dtm) = 3 THEN o.ord_amt END) wed
,SUM(CASE WHEN EXTRACT(DOW FROM o.ord_dtm) = 4 THEN o.ord_amt END) thu
,SUM(CASE WHEN EXTRACT(DOW FROM o.ord_dtm) = 5 THEN o.ord_amt END) fri
,SUM(CASE WHEN EXTRACT(DOW FROM o.ord_dtm) = 6 THEN o.ord_amt END) sat
FROM startdbpg.tr_ord_big o
WHERE o.ord_dtm >= '2024-01-01'
AND o.ord_dtm < '2024-02-01'
;
SQL
복사
실행계획 보기
SQL 결과 보기
•
주문 628,272건마다 요일 계산(EXTRACT)과 CASE를 7번씩 합니다. 약 440만 번(628,272 × 7)입니다.
GOOD: 287.450ms, hit=9134, read=0
요일별 선집계 후 CASE로 컬럼 전환
SELECT MAX(CASE WHEN t1.day_of_wk = 0 THEN t1.ord_amt_sum END) sun
,MAX(CASE WHEN t1.day_of_wk = 1 THEN t1.ord_amt_sum END) mon
,MAX(CASE WHEN t1.day_of_wk = 2 THEN t1.ord_amt_sum END) tue
,MAX(CASE WHEN t1.day_of_wk = 3 THEN t1.ord_amt_sum END) wed
,MAX(CASE WHEN t1.day_of_wk = 4 THEN t1.ord_amt_sum END) thu
,MAX(CASE WHEN t1.day_of_wk = 5 THEN t1.ord_amt_sum END) fri
,MAX(CASE WHEN t1.day_of_wk = 6 THEN t1.ord_amt_sum END) sat
FROM (
SELECT EXTRACT(DOW FROM o.ord_dtm) day_of_wk
,SUM(o.ord_amt) ord_amt_sum
FROM startdbpg.tr_ord_big o
WHERE o.ord_dtm >= '2024-01-01'
AND o.ord_dtm < '2024-02-01'
GROUP BY EXTRACT(DOW FROM o.ord_dtm)
) t1
;
SQL
복사
실행계획 보기
SQL 결과 보기
•
요일 계산은 주문마다 한 번씩만 하고(628,272번), 요일별로 먼저 합산해 7행으로 줄입니다. CASE는 7행 × 7 = 49번만 합니다.
•
요일별로 이미 1행이므로 MAX는 해당 요일의 합계 금액을 꺼내는 역할입니다.
•
읽은 양(hit 9,134)은 같습니다. 줄어든 건 계산 횟수입니다.
KEY POINT
•
대량 행에 CASE를 여러 개 쓰면, 행 수 × CASE 개수만큼 계산이 반복됩니다.
•
GROUP BY로 먼저 집계해 행을 줄인 뒤, CASE로 컬럼을 나눕니다.
•
읽는 양이 같아도 계산 횟수가 줄면 빨라집니다.
TIP. 언제 효과가 큰가?
•
CASE가 2~3개이거나 대상 행이 적으면 차이가 거의 없습니다.
•
행이 많고 CASE가 많을수록(이 예제는 62만 건 × 7개) 효과가 큽니다.
DEEP DIVE — SQL STARTER for MySQL


