Skip to content
튜닝 연습파티션
PART-004

마감 재집계에 정정 요청 주문을 함께 넣자 한 달 집계가 36개월 칸을 다 연다

기초SELECT한빛유통379 / 700

상황 ​

정산팀의 「월 마감 재집계」는 마감할 달을 고르면 그 달 주문의 상태별 건수와 금액을 다시 계산한다. 월초 마감 주간에는 하루 수백 번 호출된다. 지난주부터 고객센터가 정정을 요청한 주문은 주문한 달과 상관없이 이번 마감에 함께 넣으라는 요구가 붙었다. 조민우가 조건에 OR ADJ_YN = 'Y' 한 줄을 더한 뒤로 0.01초에 끝나던 조회가 0.12초가 되었다. 화면은 :v_ym = '202406'을 넘긴다.

테이블과 인덱스 ​

  • T_ORD_BIG_P14 주문(파티션 복사본, 교재 14화): T_ORD_BIG 1,000,000행을 PARTITION BY RANGE (ORD_DT) 월별 36칸(P202201 ~ P202412)과 빈 PMAX 1칸, 모두 37칸으로 나눴다. P202406은 30번째 칸이다. 칸 하나를 FULL로 읽으면 약 161블록, 37칸을 다 읽으면 5,868블록이다. 빈 PMAX는 세그먼트가 없다.
  • 이 문제에서는 정정 요청 표시 ADJ_YN VARCHAR2(1)이 더해져 있다(문제 설정). 정정 요청이 걸린 주문만 'Y'이고 나머지는 NULL이라 블록 수는 그대로다. 'Y'는 352건이고 36칸에 고루 흩어져 있으며, 그중 2024년 6월 주문은 12건이다.
  • ORD_DT는 NOT NULL이고 전부 자정이다. 2024년 6월은 27,390행이다.
  • LOCAL 인덱스 IX_P14_ADJ (ADJ_YN): NULL은 인덱스에 들어가지 않으므로 칸마다 블록 1개다. ORD_DT에는 인덱스가 없다. 통계는 최신이다.

원본 SQL ​

sql
SELECT ORD_ST, COUNT(*) AS ord_cnt, SUM(ORD_AMT) AS ord_amt
  FROM T_ORD_BIG_P14
 WHERE (ORD_DT >= TO_DATE(:v_ym, 'YYYYMM')
        AND ORD_DT < ADD_MONTHS(TO_DATE(:v_ym, 'YYYYMM'), 1))
    OR ADJ_YN = 'Y'
 GROUP BY ORD_ST

실행계획 학습용 예시 · 교재 14화 실측 규모 ​

xplan
-------------------------------------------------------------------------------------------------------------------
| Id  | Operation             | Name          | Starts | E-Rows | A-Rows |      A-Time | Buffers | Pstart | Pstop |
-------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |               |      1 |        |      3 | 00:00:00.12 |    5868 |        |       |
|   1 |  HASH GROUP BY        |               |      1 |      3 |      3 | 00:00:00.12 |    5868 |        |       |
|   2 |   PARTITION RANGE ALL |               |      1 |  27740 |  27730 | 00:00:00.11 |    5868 |      1 |    37 |
|*  3 |    TABLE ACCESS FULL  | T_ORD_BIG_P14 |     36 |  27740 |  27730 | 00:00:00.10 |    5868 |      1 |    37 |
-------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   3 - filter((("ORD_DT">=TO_DATE(:V_YM,'YYYYMM') AND "ORD_DT"<ADD_MONTHS(TO_DATE(:V_YM,'YYYYMM'),1))
              OR "ADJ_YN"='Y'))

문제 ​

  1. 실행계획의 어느 항목에서 칸을 전부 열었다는 것을 알 수 있는지 쓰고, 조건에 그 달의 범위가 그대로 있는데도 칸을 고르지 못하는 까닭을 설명하시오.
  2. 결과가 바뀌지 않게 SQL을 고쳐 그 달의 주문은 그 달 칸에서만 읽게 하시오. 두 조건에 모두 맞는 주문을 한 번만 세는 방법과 읽는 블록 수가 어떻게 바뀌는지도 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자