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

프루닝이 안 된다며 날짜를 SQL에 이어 붙인 뒤 하드 파싱이 하루 4천 번으로 늘었다

기초SELECT한빛유통383 / 700

상황 ​

정산 화면의 「기간 매출」은 시작일과 종료일을 골라 그 기간의 완료 주문 건수와 금액을 낸다. 하루 약 4천 번 호출되고, 고르는 기간은 대부분 한 달 안이다. 지난달 T_ORD_BIG_P14로 옮긴 뒤 조민우가 실행계획의 Pstart와 Pstop에 KEY가 찍힌 것을 보고 "바인드 변수 때문에 프루닝이 안 된다"며 날짜를 SQL 문자열에 이어 붙이도록 바꿨다. 이번 주 AWR에서 하드 파싱이 하루 약 4,100번으로 늘었고, 공유 풀 경합 대기가 새로 보인다.

테이블과 인덱스 ​

  • T_ORD_BIG_P14 주문(파티션 복사본, 교재 14화): 1,000,000행 · PARTITION BY RANGE (ORD_DT) 월별 36칸(P202201 ~ P202412)과 빈 PMAX, 모두 37칸. P202406은 30번째 칸이고 FULL로 약 161블록이다.
  • ORD_DT는 DATE이고 전부 자정이다. 하루 주문은 약 913건이고, ORD_ST는 COMPLETE가 90%다.
  • 인덱스는 없다. 통계는 최신이다.

원본 SQL ​

sql
-- 지금 : 화면이 날짜를 SQL 문자열에 이어 붙인다 (2024-06-10 ~ 2024-06-20)
SELECT COUNT(*) AS cnt, SUM(ORD_AMT) AS amt
  FROM T_ORD_BIG_P14
 WHERE ORD_ST = 'COMPLETE'
   AND ORD_DT >= TO_DATE('20240610', 'YYYYMMDD')
   AND ORD_DT <  TO_DATE('20240621', 'YYYYMMDD')

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

xplan
[지금 — 리터럴 · 2024-06-10 ~ 2024-06-20]
----------------------------------------------------------------------------------------------------------------------
| Id  | Operation                | Name          | Starts | E-Rows | A-Rows |      A-Time | Buffers | Pstart | Pstop |
----------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |               |      1 |        |      1 | 00:00:00.01 |     161 |        |       |
|   1 |  SORT AGGREGATE          |               |      1 |      1 |      1 | 00:00:00.01 |     161 |        |       |
|   2 |   PARTITION RANGE SINGLE |               |      1 |   9015 |   9039 | 00:00:00.01 |     161 |     30 |    30 |
|*  3 |    TABLE ACCESS FULL     | T_ORD_BIG_P14 |      1 |   9015 |   9039 | 00:00:00.01 |     161 |     30 |    30 |
----------------------------------------------------------------------------------------------------------------------

   3 - filter(("ORD_ST"='COMPLETE' AND "ORD_DT">=TO_DATE(' 2024-06-10 00:00:00', 'syyyy-mm-dd hh24:mi:ss')
              AND "ORD_DT"<TO_DATE(' 2024-06-21 00:00:00', 'syyyy-mm-dd hh24:mi:ss')))

[지난달 — 바인드 변수 · 같은 기간 (:v_from = '20240610', :v_to = '20240620')]
-------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name          | Starts | E-Rows | A-Rows |      A-Time | Buffers | Pstart | Pstop |
-------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |               |      1 |        |      1 | 00:00:00.01 |     161 |        |       |
|   1 |  SORT AGGREGATE             |               |      1 |      1 |      1 | 00:00:00.01 |     161 |        |       |
|*  2 |   FILTER                    |               |      1 |        |   9039 | 00:00:00.01 |     161 |        |       |
|   3 |    PARTITION RANGE ITERATOR |               |      1 |   9015 |   9039 | 00:00:00.01 |     161 |    KEY |   KEY |
|*  4 |     TABLE ACCESS FULL       | T_ORD_BIG_P14 |      1 |   9015 |   9039 | 00:00:00.01 |     161 |    KEY |   KEY |
-------------------------------------------------------------------------------------------------------------------------

   2 - filter(TO_DATE(:V_FROM,'YYYYMMDD')<TO_DATE(:V_TO,'YYYYMMDD')+1)
   4 - filter(("ORD_ST"='COMPLETE' AND "ORD_DT">=TO_DATE(:V_FROM,'YYYYMMDD') AND "ORD_DT"<TO_DATE(:V_TO,'YYYYMMDD')+1))

[AWR 하루 요약 — 바꾸기 전 → 바꾼 뒤]
  parse count (hard)                   41 → 4,112
  이 화면의 SQL 문장 수 (V$SQLAREA)      1 → 3,958   (FORCE_MATCHING_SIGNATURE 는 하나)
  Top 대기                             latch: shared pool · library cache: mutex X 가 새로 보인다

문제 ​

  1. Pstart와 Pstop의 KEY가 무슨 뜻인지 쓰고, 지난달 바인드 변수판도 6월 칸 하나만 읽었다는 것을 실행계획의 어느 숫자로 알 수 있는지 설명하시오.
  2. SQL을 바인드 변수판으로 되돌려 쓰고, 리터럴판의 대가를 설명하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자