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

1분마다 새로 고치는 「오늘 주문 건수」 타일이 건수 하나에 1,376블록을 읽는다

기초SELECT버거121 / 700

상황 ​

버거원 본사 상황판의 「오늘 주문 건수」 타일은 1분마다 새로 고친다. 지난달 코드 리뷰에서 한 개발자가 COUNT(*)를 COUNT(SHOP_NO)로 바꿨다. 리뷰 메모는 이렇다. "별표는 모든 컬럼을 읽으니 컬럼 하나만 세는 것이 빠르다." 그 뒤로 이 타일 SQL이 AWR의 'SQL ordered by Gets' 상위에 올라왔다. 아래는 2013년 12월 24일을 골랐을 때다.

테이블과 인덱스 ​

  • ORD_RANDOM(운영본): 1,000,000행 · 22,414블록 · 무작위 순서로 적재 · ORD_DT VARCHAR2(8) · 하루 약 1,370건(2013-12-24 1,368건)
  • SHOP_NO VARCHAR2(10)는 NULL 허용으로 선언되어 있다(지금 NULL은 0건)
  • 인덱스 ORD_RANDOM_PK (ORD_NO) · ORD_RANDOM_X01 (ORD_DT, ORD_HMS): BLEVEL 2 · 리프 3,774블록 · CLUSTERING_FACTOR 999,958 · 통계 최신

원본 SQL ​

sql
SELECT COUNT(SHOP_NO) AS ord_cnt
  FROM ORD_RANDOM
 WHERE ORD_DT = :v_dt

실행계획 학습용 예시 · CF는 교재 04화 실측 ​

xplan
-------------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |                |      1 |        |      1 |00:00:00.02 |    1376 |
|   1 |  SORT AGGREGATE                      |                |      1 |      1 |      1 |00:00:00.02 |    1376 |
|   2 |   TABLE ACCESS BY INDEX ROWID BATCHED| ORD_RANDOM     |      1 |   1370 |   1368 |00:00:00.02 |    1376 |
|*  3 |    INDEX RANGE SCAN                  | ORD_RANDOM_X01 |      1 |   1370 |   1368 |00:00:00.01 |       8 |
-------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   3 - access("ORD_DT"=:V_DT)

문제 ​

  1. 3번 줄에서 인덱스를 8블록만 읽고도 2번 줄에서 1,368블록을 더 읽는 이유를 설명하시오. 리뷰 메모가 왜 틀렸는지도 설명하시오.
  2. 같은 건수를 인덱스만으로 세도록 SQL을 고치시오. COUNT(SHOP_NO)와 COUNT(*)는 뜻도 다를 수 있다는 점을 설명하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자