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

매장 한 곳의 하루치 판매를 보는데 판매상품 테이블을 통째로 읽는다

기초SELECT유통595 / 700

상황 ​

본사 레거시 유통의 점장 화면 「어제 상품별 판매」는 매장 여섯 곳의 점장이 아침마다 수십 번씩 누른다. 조민우가 전했다. "매장 한 곳, 하루치인데 0.4초씩 걸리고 아침에는 화면이 밀려요." 이 DB는 2016년에 자동 통계 수집을 껐다. 그 뒤로는 DBA가 만든 야간 잡 PKG_STATS.NIGHTLY가 목록 표 STATS_TARGET에 적힌 테이블만 매일 23:40에 모은다. 목록은 사람이 손으로 고친다.

테이블과 인덱스 ​

  • CF10 판매: 500,000행 · 4,583블록 · SLE_DT VARCHAR2(8) · 하루 약 700건 · 매장 6곳(SHP_NO) · 통계는 어젯밤 23:41(목록에 있다)
  • CF11 판매상품: 실제 1,096,708행 · 8,204블록 · CF11_PK (SLE_NO, ITM_NO) · 판매 한 건에 평균 2.2줄
  • CF11의 통계는 NUM_ROWS 109,860 · BLOCKS 822 · 마지막 수집 2019-03-14(2019년 이관 때 목록에서 빠졌다)
  • 인덱스: CF10_PK (SLE_NO) · IX_CF10_DT_SHP (SLE_DT, SHP_NO) · CF11_PK

원본 SQL ​

sql
SELECT b.ITM_NO, SUM(b.SLE_QTY) AS qty, SUM(b.SLE_QTY * b.SLE_UPRC) AS amt
  FROM CF10 a, CF11 b
 WHERE a.SLE_DT = :dt
   AND a.SHP_NO = :shp
   AND b.SLE_NO = a.SLE_NO
 GROUP BY b.ITM_NO

실행계획 학습용 예시 ​

xplan
[USER_TAB_STATISTICS — 오늘 08:50]
 TABLE_NAME   NUM_ROWS  BLOCKS  LAST_ANALYZED   STALE_STATS   실제 COUNT(*)
 CF10          500,000   4,583  어제 23:41      NO                  500,000
 CF11          109,860     822  2019-03-14      YES               1,096,708
 (USER_TAB_MODIFICATIONS — CF11 : INSERTS 986,848 · 마지막 수집 이후)

-----------------------------------------------------------------------------------------------------------
| Id  | Operation                             | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                      |                |      1 |        |     64 |00:00:00.41 |    8215 |
|   1 |  HASH GROUP BY                        |                |      1 |     61 |     64 |00:00:00.41 |    8215 |
|*  2 |   HASH JOIN                           |                |      1 |    250 |    256 |00:00:00.41 |    8215 |
|   3 |    TABLE ACCESS BY INDEX ROWID BATCHED| CF10           |      1 |    114 |    117 |00:00:00.01 |      11 |
|*  4 |     INDEX RANGE SCAN                  | IX_CF10_DT_SHP |      1 |    114 |    117 |00:00:00.01 |       3 |
|   5 |    TABLE ACCESS FULL                  | CF11           |      1 |    109K|   1096K|00:00:00.30 |    8204 |
-----------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("B"."SLE_NO"="A"."SLE_NO")
   4 - access("A"."SLE_DT"=:DT AND "A"."SHP_NO"=:SHP)

문제 ​

  1. 실행계획의 어느 줄에서 옵티마이저가 무엇을 잘못 알고 있는지 찾고, 그 숫자가 어디서 왔는지 쓰시오.
  2. 그 숫자 때문에 이 계획을 고른 이유를 쓰고, 오늘 할 조치와 같은 일이 다시 생기지 않게 할 조치를 SQL로 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자