테마
마케팅팀은 매달 초 리포팅 도구로 「고객별 주문 원장」을 CSV로 내려받는다. 고객 번호, 주문일 순으로 100만 행 전부다. 다운로드는 바로 시작되는데 끝나기까지 오래 걸리고, 그동안 서버 CPU 하나가 계속 바쁘다.
리포팅 도구는 접속할 때마다 세션을 OPTIMIZER_MODE = FIRST_ROWS_10으로 바꾼다. 공급사는 이렇게 설명한다. "첫 화면을 빨리 띄우기 위한 기본값이다." 같은 SQL을 SQL*Plus(ALL_ROWS)에서 돌리면 계획이 다르다.
T_ORD_BIG: 1,000,000행 · 5,826블록(블록당 약 172행) · ORD_SEQ 순으로 쌓였다 · CUS_ID NOT NULL 2,000명 · 한 고객의 주문은 ORD_SEQ 2,000건 간격이라 테이블 전체에 흩어져 있다IX_ORD_BIG_CUS_DT (CUS_ID, ORD_DT): 「고객 주문 이력」(CUS_ID = :c) 화면용 · BLEVEL 2 · 리프 약 3,600블록 · CLUSTERING_FACTOR 약 1,000,000 · 통계 최신 · 다른 인덱스는 이 SQL과 상관없다-- 리포팅 도구 세션: ALTER SESSION SET OPTIMIZER_MODE = FIRST_ROWS_10;
SELECT CUS_ID, ORD_DT, ORD_AMT
FROM T_ORD_BIG
ORDER BY CUS_ID, ORD_DT
[리포팅 도구 — FIRST_ROWS_10]
----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1000K|00:00:04.62 | 1003K|
| 1 | TABLE ACCESS BY INDEX ROWID| T_ORD_BIG | 1 | 1000K| 1000K|00:00:04.62 | 1003K|
| 2 | INDEX FULL SCAN | IX_ORD_BIG_CUS_DT | 1 | 1000K| 1000K|00:00:00.41 | 3603 |
----------------------------------------------------------------------------------------------------------
(0번 줄 Buffers 정확한 값 1,003,603 · 버퍼 캐시에 테이블이 다 올라와 있을 때)
[SQL*Plus — ALL_ROWS]
-------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | Writes | Used-Mem | Used-Tmp |
-------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1000K|00:00:01.71 | 5826 | 4102 | 4102 | | |
| 1 | SORT ORDER BY | | 1 | 1000K| 1000K|00:00:01.71 | 5826 | 4102 | 4102 | 2142K (1)| 33M |
| 2 | TABLE ACCESS FULL| T_ORD_BIG | 1 | 1000K| 1000K|00:00:00.09 | 5826 | 0 | 0 | | |
-------------------------------------------------------------------------------------------------------------------------------
SQL*Plus에서는 5,826블록과 TEMP 33MB를 쓰는 이유를 두 실행계획의 스캔 방식과 OPTIMIZER_MODE로 설명하시오.