Skip to content
튜닝 연습인덱스 스캔 효율과 테이블 액세스
ACC-040

인덱스를 더 만들 수 없는 주문 테이블에서 주간 주문번호 대사 파일이 9천 블록을 읽는다

실전SELECT버거115 / 700

상황 ​

버거원 본사 회계팀은 매주 월요일 지난주 주문의 주문번호와 주문 일시를 내려받아 PG사 정산 파일과 맞춘다. 감사 기간에는 한 달 치를 받는다. 주간 파일 하나에 6초 넘게 걸리고, 그동안 POS 적재 세션의 응답이 늦어진다는 민원이 들어왔다. 본사 DBA 규정에는 이런 줄이 있다. "ORD_RANDOM에는 인덱스를 더 만들지 않는다(2013년 POS 장애 뒤 결정)." 박팀장은 이렇게 주문했다. "인덱스 없이 할 수 있는 것부터, 대가까지 적어 와라."

테이블과 인덱스 ​

  • ORD_RANDOM(운영본): 1,000,000행 · 22,414블록(블록당 약 45행) · 서버 교체 때 무작위 순서로 다시 적재했다 · ORD_DT VARCHAR2(8) 2012 ~ 2013(하루 약 1,370건) · 2013-12-02 ~ 12-08 주문 9,589건 · ORD_NO NUMBER(10)은 PK라 NOT NULL
  • 인덱스 ORD_RANDOM_PK (ORD_NO): BLEVEL 2 · 리프 약 2,090블록 · ORD_RANDOM_X01 (ORD_DT, ORD_HMS): BLEVEL 2 · 리프 3,774블록 · CLUSTERING_FACTOR 999,958(교재 04화 실측) · 통계 최신
  • 같은 조건을 FULL로 읽으면 22,234블록이다(교재 04화 실측) · db_file_multiblock_read_count = 128
  • 보관본 ORD: 내용이 같고 주문 시각 순으로 쌓였다 · ORD_X01의 CLUSTERING_FACTOR 22,223
  • ORD_DT가 문자라서 옵티마이저는 기간의 행 수를 실제보다 열 배쯤 낮게 본다(교재 04화 §5)

원본 SQL ​

sql
SELECT ORD_NO, ORD_DT, ORD_HMS
  FROM ORD_RANDOM
 WHERE ORD_DT BETWEEN :v_from AND :v_to
 ORDER BY ORD_DT, ORD_HMS

실행계획 학습용 예시 · CF와 FULL 블록 수는 교재 04화 실측 ​

xplan
---------------------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads |
---------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                |      1 |        |   9589 |00:00:06.31 |    9631 |  9418 |
|*  1 |  FILTER                      |                |      1 |        |   9589 |00:00:06.31 |    9631 |  9418 |
|   2 |   TABLE ACCESS BY INDEX ROWID| ORD_RANDOM     |      1 |    950 |   9589 |00:00:06.30 |    9631 |  9418 |
|*  3 |    INDEX RANGE SCAN          | ORD_RANDOM_X01 |      1 |    950 |   9589 |00:00:00.02 |      42 |    38 |
---------------------------------------------------------------------------------------------------------------

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

[세션 통계] physical read total IO requests 9,418 (multi block 0) · db file sequential read 9,418회 · 5.9초

문제 ​

  1. 9,631블록의 대부분이 어디서 나오는지 실행계획과 CLUSTERING_FACTOR로 설명하시오.
  2. 인덱스를 만들지 않는 처방과 인덱스를 바꾸는 처방을 합쳐 넷 이상 들어 Buffers, I/O 방식, 대가를 비교하시오. 그중 지금 적용할 것을 골라 SQL을 작성하시오.
  3. 고른 처방이 테이블 액세스보다 유리해지는 기간이 대략 며칠부터인지 구하시오. 같은 처방을 보관본 ORD에 쓰면 어떻게 되는지도 설명하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자