테마
CRM팀은 매달 1일 고객 2,000명 모두에게 지난달 주문 건수와 금액을 붙인 파일을 받는다. 주문이 없는 고객도 0건으로 나와야 해서 아우터 조인으로 썼고, 지금까지는 0.03초 만에 끝났다.
지난달 「선물하기」를 열면서 선물로 받은 주문도 받은 고객의 실적으로 세기로 했다. 개발자는 ON 절의 조인 조건에 OR o.RCV_CUS_ID = c.CUS_ID를 더했고, 현업은 건수와 합계를 검수해 맞다고 했다. 그 뒤로 추출이 18초 걸린다. DB는 19c이고 옵티마이저 설정은 기본값이다. 아래는 2024년 6월로 돌린 실행계획이다.
M_CUS 고객: 2,000행 · 30블록 · PK_M_CUS (CUS_ID)T_ORD 주문: 100,000행 · 896블록 · PK_T_ORD (ORD_SEQ) 말고는 인덱스가 없다 · 통계 최신T_ORD에는 RCV_CUS_ID(선물 받은 회원) 칸이 있다. 회원이 받는 주문에만 값이 있고, 본인이 받으면 CUS_ID와 같은 번호가 들어간다. 비회원이 주문하면 CUS_ID가 NULL이다SELECT c.CUS_ID, c.CUS_NM,
COUNT(o.ORD_SEQ) AS ord_cnt,
NVL(SUM(o.ORD_AMT), 0) AS ord_amt
FROM M_CUS c
LEFT JOIN T_ORD o
ON (o.CUS_ID = c.CUS_ID OR o.RCV_CUS_ID = c.CUS_ID)
AND o.ORD_DT >= TO_DATE(:v_ym, 'YYYYMM')
AND o.ORD_DT < ADD_MONTHS(TO_DATE(:v_ym, 'YYYYMM'), 1)
GROUP BY c.CUS_ID, c.CUS_NM
ORDER BY c.CUS_ID
------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 2000 |00:00:18.42 | 1792K |
| 1 | SORT GROUP BY | | 1 | 2000 | 2000 |00:00:18.42 | 1792K |
| 2 | NESTED LOOPS OUTER | | 1 | 8340 | 4718 |00:00:18.40 | 1792K |
| 3 | TABLE ACCESS FULL | M_CUS | 1 | 2000 | 2000 |00:00:00.01 | 30 |
| 4 | VIEW | VW_LAT_5E1D7B42 | 2000 | 4 | 4470 |00:00:18.37 | 1792K |
|* 5 | TABLE ACCESS FULL | T_ORD | 2000 | 4 | 4470 |00:00:18.35 | 1792K |
------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
5 - filter(("O"."ORD_DT">=TO_DATE(:V_YM,'YYYYMM') AND "O"."ORD_DT"<ADD_MONTHS(TO_DATE(:V_YM,'YYYYMM'),1)
AND ("O"."CUS_ID"="C"."CUS_ID" OR "O"."RCV_CUS_ID"="C"."CUS_ID")))
Starts로 설명하시오. OR를 더하기 전처럼 해시 조인을 쓰지 못한 이유를 조인 조건으로 설명하고, 19c 옵티마이저가 이 OR를 스스로 두 갈래로 나누지 않았다는 것을 계획의 어디에서 알 수 있는지도 쓰시오.