Skip to content
튜닝 연습서브쿼리와 쿼리 변환
SUBQ-026

재구매 감사 쿠폰이 고객 한 명에게 두세 장씩 나갔다

기초INSERT이커머스261 / 700

이 문제는 교재 18화 졸업 과제와 같은 이커머스 데이터베이스를 씁니다. 『튜너의 1년』을 순서대로 읽고 있다면 졸업 과제를 먼저 풀고 오세요. 아래 「테이블과 인덱스」 칸에 과제의 답 일부(제약 조건, 인덱스, 통계의 실제 상태)가 나옵니다.

상황 ​

마케팅팀은 11월에 주문한 고객에게 감사 쿠폰을 한 장씩 주기로 했다. 개발자는 처음에 IN 서브쿼리로 짰다가 "조인이 더 빠르다"는 말을 듣고 조인으로 바꿔 배포했다. 발급 다음 날 고객센터에 "쿠폰이 세 장 왔다"는 문의가 들어왔다.

테이블과 인덱스 ​

  • customers 고객: 5,230행 · 51블록 · PK(customer_id)만 있다
  • orders 주문: 34,908행 · 193블록 · PK(order_id)만 있고 customer_id에는 인덱스가 없다 · 2024년 11월 주문 582건, 주문한 고객 523명(두 번 주문 53명, 세 번 주문 3명)
  • coupon_issue 쿠폰 발급: 이번 행사를 위해 만든 테이블 (customer_id, coupon_cd, issued_at) · 제약과 인덱스 없음
  • 통계 최신

원본 SQL ​

sql
INSERT INTO coupon_issue (customer_id, coupon_cd, issued_at)
SELECT c.customer_id, 'THX2411', SYSDATE
  FROM customers c, orders o
 WHERE o.customer_id = c.customer_id
   AND o.order_date >= DATE '2024-11-01'
   AND o.order_date <  DATE '2024-12-01'

실행계획 학습용 예시 ​

xplan
-------------------------------------------------------------------------------------------------
| Id  | Operation                | Name         | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------------------
|   0 | INSERT STATEMENT         |              |      1 |        |      0 |00:00:00.02 |     822 |
|   1 |  LOAD TABLE CONVENTIONAL | COUPON_ISSUE |      1 |        |      0 |00:00:00.02 |     822 |
|*  2 |   HASH JOIN              |              |      1 |    582 |    582 |00:00:00.01 |     244 |
|*  3 |    TABLE ACCESS FULL     | ORDERS       |      1 |    582 |    582 |00:00:00.01 |     193 |
|   4 |    TABLE ACCESS FULL     | CUSTOMERS    |      1 |   5230 |   5230 |00:00:00.01 |      51 |
-------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("O"."CUSTOMER_ID"="C"."CUSTOMER_ID")
   3 - filter(("O"."ORDER_DATE">=TO_DATE(' 2024-11-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
              "O"."ORDER_DATE"<TO_DATE(' 2024-12-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss')))

문제 ​

  1. 고객 523명에게 쿠폰 582장이 나간 이유를 실행계획의 2번 줄로 설명하시오.
  2. 고객 한 명에 쿠폰 한 장만 들어가도록 SQL을 고치고, 같은 실수가 다시 나와도 중복 발급을 막을 장치를 제안하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자