Skip to content
튜닝 연습옵티마이저와 통계
OPT-033

접속 풀을 화면과 같이 쓰게 한 뒤로 연간 주문 추출 SQL이 읽은 블록 수 1위에 올랐다

기초SELECT한빛유통623 / 700

상황 ​

정산팀의 「연간 주문 추출」 배치는 매년 1월과 감사 요청이 올 때 한 해 치 주문을 파일로 내린다. 지난달 조민우가 배치 서버의 데이터소스 설정을 정리하면서 배치도 화면 서버와 같은 접속 풀(HANORDER_WEB)을 쓰게 했다. 그 뒤로 AWR의 「SQL ordered by Gets」 1위에 이 추출 SQL이 올라왔다. SQL은 한 글자도 바뀌지 않았다. 접속 풀 설정에는 2년 전에 넣은 초기화 SQL이 한 줄 있다. 목록 화면들이 첫 10행을 빨리 띄우게 하려고 넣은 줄이다.

테이블과 인덱스 ​

  • T_ORD_BIG: 1,000,000행 · 5,826블록 · ORD_DT DATE(전부 자정) · 2023년 한 해 333,245행 · 통계 최신(ORD_DT NDV 1,095)
  • 인덱스 IX_ORD_BIG_DT (ORD_DT): BLEVEL 2 · 리프 2,653블록 · 클러스터링 팩터 1,000,000(같은 날짜의 주문이 테이블 전체에 흩어져 있다)
  • 인스턴스의 OPTIMIZER_MODE는 기본값 ALL_ROWS다. 배치는 추출한 행을 끝까지 받아 파일로 쓴다(fetch size 500).
  • 접속 풀 HANORDER_WEB의 초기화 SQL: ALTER SESSION SET OPTIMIZER_MODE = FIRST_ROWS_10

원본 SQL ​

sql
SELECT ORD_SEQ, CUS_ID, ORD_DT, ORD_ST, ORD_AMT
  FROM T_ORD_BIG
 WHERE ORD_DT >= :v_from
   AND ORD_DT <  :v_to
 ORDER BY ORD_DT

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

xplan
[배치 세션 — :v_from = 2023-01-01, :v_to = 2024-01-01 · 끝까지 받은 뒤]
----------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name          | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |               |      1 |        |    333K|00:00:02.71 |     334K|
|*  1 |  FILTER                      |               |      1 |        |    333K|00:00:02.71 |     334K|
|   2 |   TABLE ACCESS BY INDEX ROWID| T_ORD_BIG     |      1 |    335K|    333K|00:00:02.58 |     334K|
|*  3 |    INDEX RANGE SCAN          | IX_ORD_BIG_DT |      1 |     10 |    333K|00:00:00.19 |     887 |
----------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(:V_FROM<:V_TO)
   3 - access("ORD_DT">=:V_FROM AND "ORD_DT"<:V_TO)

Outline Data (+OUTLINE 에서 필요한 줄만)
-------------
      FIRST_ROWS(10)
      INDEX_RS_ASC(@"SEL$1" "T_ORD_BIG"@"SEL$1" ("T_ORD_BIG"."ORD_DT"))

[V$SES_OPTIMIZER_ENV — 배치 세션]
 NAME              VALUE           ISDEFAULT
 optimizer_mode    first_rows_10   NO

(334K = 334,132 · 지난해 배치 서버 전용 풀에서 돈 같은 SQL : TABLE ACCESS FULL + SORT ORDER BY · 5,826블록)

문제 ​

  1. SQL이 그대로인데 계획이 바뀐 이유를 실행계획과 세션 정보의 어느 줄에서 알 수 있는지 쓰시오.
  2. 옵티마이저가 이 계획을 고른 이유를 최적화 목표로 설명하고, 화면은 그대로 두면서 추출만 바로잡으시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자