Skip to content
튜닝 연습소트 튜닝과 페이징
SORT-007

본사 상황판의 「방금 들어온 주문 20건」이 10초마다 22,422블록을 읽는다

기초SELECT버거312 / 700

상황 ​

본사 운영실 상황판은 전 매장의 가장 최근 주문 20건을 보여 주고 10초마다 새로 고친다. 운영실 대형 모니터 4대와 지역 담당 PC 20대가 이 화면을 띄워 두어 하루 약 20만 번 호출된다. DBA가 메시지를 보냈다. "논리 읽기 1위가 이 SQL이에요. ORD_X01 (ORD_DT, ORD_HMS) 인덱스가 있는데 왜 FULL로 읽죠?" 개발자는 일자와 시각이 따로 있으니 둘을 붙여야 정확한 시각순이 된다고 생각해 정렬 키를 ORD_DT || ORD_HMS로 썼다.

테이블과 인덱스 ​

  • ORD 주문: 1,000,000행 · 22,422블록 · 날짜순으로 적재되어 최근 주문은 테이블 끝 블록에 모여 있다 · ORD_NO PK · SHOP_NO 매장 200곳
  • ORD_DT VARCHAR2(8) '20131231' · ORD_HMS VARCHAR2(6) '235958' · 두 컬럼 모두 NOT NULL이고 늘 8자리, 6자리다(0 채움 정상)
  • 인덱스 ORD_PK (ORD_NO), ORD_X01 (ORD_DT, ORD_HMS): BLEVEL 2 · 리프 약 3,500블록 · CF 22,223 · 통계 최신

원본 SQL ​

sql
SELECT ORD_NO, SHOP_NO, ORD_DT, ORD_HMS
  FROM (SELECT o.ORD_NO, o.SHOP_NO, o.ORD_DT, o.ORD_HMS
          FROM ORD o
         ORDER BY o.ORD_DT || o.ORD_HMS DESC)
 WHERE ROWNUM <= 20

실행계획 학습용 예시 ​

xplan
--------------------------------------------------------------------------------------------------------
| Id  | Operation               | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Used-Mem |
--------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |      |      1 |        |     20 |00:00:00.27 |   22422 |          |
|*  1 |  COUNT STOPKEY          |      |      1 |        |     20 |00:00:00.27 |   22422 |          |
|   2 |   VIEW                  |      |      1 |   1000K|     20 |00:00:00.27 |   22422 |          |
|*  3 |    SORT ORDER BY STOPKEY|      |      1 |   1000K|     20 |00:00:00.27 |   22422 | 4096  (0)|
|   4 |     TABLE ACCESS FULL   | ORD  |      1 |   1000K|   1000K|00:00:00.08 |   22422 |          |
--------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(ROWNUM<=20)
   3 - filter(ROWNUM<=20)

문제 ​

  1. ORD_X01이 있는데도 4번 줄이 테이블 전체를 읽고 3번 줄이 정렬하는 이유를 설명하시오.
  2. 결과가 바뀌지 않게 SQL을 고쳐 인덱스를 거꾸로 읽다가 20건에서 멈추게 하시오. 고친 정렬이 원래 정렬과 같은 순서라고 말할 수 있는 근거도 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자