Skip to content
튜닝 연습소트 튜닝과 페이징
SORT-065

「결제수단별 월 주문 건수」 표의 카드, 계좌이체, 간편결제 세 칸이 매달 똑같은 숫자다

기초SELECT이커머스370 / 700

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

상황 ​

운영팀의 월간 보고 「결제수단별 주문 건수」는 2024년 달마다 한 줄에 결제수단 세 칸을 보여 준다. 재무팀이 PG사 정산서와 맞춰 보다가, 세 칸이 매달 똑같은 숫자이고 세 칸을 더하면 그달 주문 수의 세 배가 된다는 것을 찾았다. 보고서를 처음 만든 지 넉 달째다. 개발자는 "CASE로 결제수단마다 나눠 셌는데 왜 같은 숫자가 나오는지 모르겠다"라고 한다.

테이블과 인덱스 ​

  • orders: 34,908행 · 193블록 · order_date DATE(시분초 있음, 2020 ~ 2024) · 2024년 8,113건 · PK만
  • payments: 34,908행 · 192블록 · order_id와 1:1 · payment_method NOT NULL 3종(이 문제에서는 'CARD' 약 61% · 'BANK' 약 24% · 'EASY' 약 15%) · PK만
  • 통계 최신 · 보고서는 한 달에 한 번 돌고, 양식을 고칠 때 몇 번 더 돈다

원본 SQL ​

sql
SELECT TO_CHAR(o.order_date, 'YYYY-MM') AS ym,
       COUNT(CASE WHEN p.payment_method = 'CARD' THEN 1 ELSE 0 END) AS card_cnt,
       COUNT(CASE WHEN p.payment_method = 'BANK' THEN 1 ELSE 0 END) AS bank_cnt,
       COUNT(CASE WHEN p.payment_method = 'EASY' THEN 1 ELSE 0 END) AS easy_cnt
  FROM orders o, payments p
 WHERE p.order_id = o.order_id
   AND o.order_date >= DATE '2024-01-01'
   AND o.order_date <  DATE '2025-01-01'
 GROUP BY TO_CHAR(o.order_date, 'YYYY-MM')
 ORDER BY ym

실행계획 학습용 예시 ​

xplan
-----------------------------------------------------------------------------------------------------------
| Id  | Operation          | Name     | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Used-Mem |
-----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |          |      1 |        |     12 |00:00:00.02 |     385 |          |
|   1 |  SORT GROUP BY     |          |      1 |   8113 |     12 |00:00:00.02 |     385 | 2048  (0)|
|*  2 |   HASH JOIN        |          |      1 |   8113 |   8113 |00:00:00.02 |     385 | 1461K (0)|
|*  3 |    TABLE ACCESS FULL| ORDERS  |      1 |   8113 |   8113 |00:00:00.01 |     193 |          |
|   4 |    TABLE ACCESS FULL| PAYMENTS|      1 |  34908 |  34908 |00:00:00.01 |     192 |          |
-----------------------------------------------------------------------------------------------------------

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

[결과 · 앞의 세 달]
  ym        card_cnt  bank_cnt  easy_cnt
  2024-01        688       688       688
  2024-02        641       641       641
  2024-03        702       702       702

문제 ​

  1. 세 칸이 같은 숫자가 되는 까닭을 COUNT가 세는 기준으로 설명하시오.
  2. 결제수단별 건수가 맞게 나오도록 SQL을 고치고, CASE로 쓰는 법과 PIVOT으로 쓰는 법을 견주시오.
  3. 고친 뒤 결과를 무엇과 맞춰 보면 되는지, 읽는 블록 수는 어떻게 되는지 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자