테마
마케팅팀의 「월간 주문 채널 분석」은 한 달 주문마다 유입 채널, 쿠폰 번호, 선물 포장 여부, 할부 개월을 붙여 내려받는 추출이다. 처음에는 유입 채널 한 칸이었는데 요청이 올 때마다 칸을 하나씩 더해 지금은 네 칸이 됐고, 칸이 늘 때마다 읽는 블록도 2천여 개씩 늘었다. 마케팅팀은 다음 달에 배송 메모와 영수증 종류도 더해 달라고 한다.
부가 속성은 2021년 주문 화면 개편 때 T_ORD에 컬럼을 늘리지 않고 행으로 넣기로 한 T_ORD_ATTR에 있다. 아래는 2024년 6월로 조회한 실행계획이다.
T_ORD: 100,000행 · 896블록 · PK_T_ORD (ORD_SEQ) · 2024년 6월 4,172건(테이블 전체에 흩어져 있다)T_ORD_ATTR 주문 부가 속성(이 문제에서 쓰는 테이블): 400,000행 · 2,220블록 · ORD_SEQ · ATTR_CD · ATTR_VAL · PK_T_ORD_ATTR (ORD_SEQ, ATTR_CD) BLEVEL 2ATTR_CD 6종의 행 수: CHNL 98,800 · RCPT_TP 120,000 · DLV_MSG 81,200 · PAY_INST 60,000 · CPN 30,000 · GIFT_YN 10,000 · ATTR_CD에 히스토그램 있음CHNL 4,135 · PAY_INST 2,497 · CPN 1,254 · GIFT_YN 418 · 네 속성이 모두 없는 주문 37건(콜센터 전화 주문) · 통계 최신SELECT o.ORD_SEQ, o.ORD_DT, o.ORD_AMT,
a1.ATTR_VAL AS chnl, a2.ATTR_VAL AS cpn_no,
a3.ATTR_VAL AS gift_yn, a4.ATTR_VAL AS pay_inst
FROM T_ORD o
LEFT JOIN T_ORD_ATTR a1 ON a1.ORD_SEQ = o.ORD_SEQ AND a1.ATTR_CD = 'CHNL'
LEFT JOIN T_ORD_ATTR a2 ON a2.ORD_SEQ = o.ORD_SEQ AND a2.ATTR_CD = 'CPN'
LEFT JOIN T_ORD_ATTR a3 ON a3.ORD_SEQ = o.ORD_SEQ AND a3.ATTR_CD = 'GIFT_YN'
LEFT JOIN T_ORD_ATTR a4 ON a4.ORD_SEQ = o.ORD_SEQ AND a4.ATTR_CD = 'PAY_INST'
WHERE o.ORD_DT >= :v_from
AND o.ORD_DT < :v_to
------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Used-Mem |
------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 4172 |00:00:00.21 | 9776 | |
|* 1 | HASH JOIN OUTER | | 1 | 4172 | 4172 |00:00:00.21 | 9776 | 1586K (0) |
|* 2 | HASH JOIN OUTER | | 1 | 4172 | 4172 |00:00:00.16 | 7556 | 1586K (0) |
|* 3 | HASH JOIN OUTER | | 1 | 4172 | 4172 |00:00:00.11 | 5336 | 1586K (0) |
|* 4 | HASH JOIN OUTER | | 1 | 4172 | 4172 |00:00:00.06 | 3116 | 1452K (0) |
|* 5 | TABLE ACCESS FULL | T_ORD | 1 | 4172 | 4172 |00:00:00.01 | 896 | |
|* 6 | TABLE ACCESS FULL | T_ORD_ATTR | 1 | 98800 | 98800 |00:00:00.03 | 2220 | |
|* 7 | TABLE ACCESS FULL | T_ORD_ATTR | 1 | 30000 | 30000 |00:00:00.03 | 2220 | |
|* 8 | TABLE ACCESS FULL | T_ORD_ATTR | 1 | 10000 | 10000 |00:00:00.03 | 2220 | |
|* 9 | TABLE ACCESS FULL | T_ORD_ATTR | 1 | 60000 | 60000 |00:00:00.03 | 2220 | |
------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A4"."ORD_SEQ"="O"."ORD_SEQ")
2 - access("A3"."ORD_SEQ"="O"."ORD_SEQ")
3 - access("A2"."ORD_SEQ"="O"."ORD_SEQ")
4 - access("A1"."ORD_SEQ"="O"."ORD_SEQ")
5 - filter(("O"."ORD_DT">=:V_FROM AND "O"."ORD_DT"<:V_TO))
6 - filter("A1"."ATTR_CD"='CHNL')
7 - filter("A2"."ATTR_CD"='CPN')
8 - filter("A3"."ATTR_CD"='GIFT_YN')
9 - filter("A4"."ATTR_CD"='PAY_INST')
T_ORD_ATTR를 한 번만 읽도록 SQL을 고치시오. 결과 행 수와 각 칸의 값이 원래 SQL과 같아야 하며, 그렇게 되는 근거를 쓰시오.