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

「버거류 일 판매」가 인덱스를 1,485블록 읽는데 자이언트더블버거가 빠져 있다

실전SELECT버거94 / 700

상황 ​

버거원 상품기획팀의 「버거류 일 판매」는 날짜 하나를 고르면 버거 메뉴별 판매 수량을 보여 준다. 하루 수백 번 연다. 2년 전 개발자는 버거 메뉴의 ITEM_ID가 1 ~ 17이라 BETWEEN 1 AND 17로 썼다. 상품기획팀이 "자이언트더블버거가 목록에 없다"고 문의했고, 같은 시기에 이 화면이 인덱스를 1,485블록 읽는다는 점검 결과도 나왔다. 자이언트더블버거는 나중에 추가된 메뉴로 ITEM_ID가 84다.

테이블과 인덱스 ​

  • ORD_ITEM 주문상품: 2,472,717행 · 55,265블록 · ITEM_ID 1 ~ 92에 고르게 분포(상품당 약 26,900행, 하루 약 37행) · ORD_DT VARCHAR2(8) 2012 ~ 2013 · 2013-11-15 하루 약 3,430행
  • ITEM 상품: 92행 · 5블록 · ITEM_PK (ITEM_ID) · ITEM_TYPE_CD 100100 버거 18종(1 ~ 17과 84) · 100101 세트 · 100102 치킨 · 100103 디저트 · 100104 아이스크림 · 100105 음료
  • 번호 대역과 분류가 맞지 않는 메뉴가 이미 있다(예: 74 치즈스틱은 디저트인데 음료 번호 사이에 있다)
  • 인덱스 ORD_ITEM_PK (ORD_NO, ITEM_ID) · ORD_ITEM_X01 (ORD_DT, ORD_HMS) · ORD_ITEM_X02 (ITEM_ID, ORD_DT, ORD_ITEM_QTY): BLEVEL 2 · 리프 약 8,500블록(리프 한 블록에 약 290항목) · 「상품 월간 추이」가 쓴다

원본 SQL ​

sql
SELECT ITEM_ID, SUM(ORD_ITEM_QTY) AS qty
  FROM ORD_ITEM
 WHERE ITEM_ID BETWEEN 1 AND 17
   AND ORD_DT = :v_dt
 GROUP BY ITEM_ID
 ORDER BY ITEM_ID

실행계획 학습용 예시 · 규모는 schemas 그대로 · 상품 분류는 적재 스크립트(2.sql) 그대로 ​

xplan
---------------------------------------------------------------------------------------------
| Id  | Operation            | Name         | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |              |      1 |        |     17 |00:00:00.03 |    1485 |
|   1 |  SORT GROUP BY NOSORT|              |      1 |     17 |     17 |00:00:00.03 |    1485 |
|*  2 |   INDEX RANGE SCAN   | ORD_ITEM_X02 |      1 |    667 |    631 |00:00:00.03 |    1485 |
---------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("ITEM_ID">=1 AND "ORD_DT"=:V_DT AND "ITEM_ID"<=17)
       filter("ORD_DT"=:V_DT)

문제 ​

  1. 2번 줄이 1,485블록을 읽는 이유를 access와 filter로 설명하시오. 결과에서 자이언트더블버거가 빠진 이유도 설명하시오.
  2. 세 가지 고침을 비교하시오. ① ITEM_ID IN (1, 2, …, 17, 84) ② ITEM에서 버거 분류(ITEM_TYPE_CD = '100100')를 읽어 조인 ③ 새 인덱스 (ORD_DT, ITEM_ID, ORD_ITEM_QTY). 각각 읽는 블록 수, 결과가 맞는지, 메뉴가 늘거나 바뀔 때 생기는 일, 적재 비용을 쓰시오.
  3. 하나를 골라 SQL(필요하면 DDL)을 작성하고, 고른 방식의 실행계획에서 ORD_ITEM_X02가 몇 번, 어떤 조건으로 읽히는지 설명하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자