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

택배사 연동 폴링이 배송 테이블을 하루 8,640번 통째로 읽는데, 인덱스 제안이 셋이다

실전DDL이커머스137 / 700

이 문제는 교재 18화 졸업 과제와 같은 이커머스 데이터베이스를 씁니다. 『튜너의 1년』을 순서대로 읽고 있다면 졸업 과제를 먼저 풀고 오세요. 아래 「테이블과 인덱스」 칸에 과제의 답 일부(제약 조건, 인덱스, 통계의 실제 상태)가 나옵니다.

상황 ​

신규 이커머스는 택배사 연동 배치가 10초마다 출고 대기(READY) 배송을 찾아 택배사로 넘긴다. 운영 대시보드는 1분마다 배송 상태별 건수를 새로 그린다. 둘 다 shipping을 통째로 읽어 AWR의 'SQL ordered by Gets' 1, 2위에 올라 있다. 인덱스 제안이 셋 들어왔다. 조민우는 "상태가 넷뿐이니 비트맵", 선배는 "출고 대기만 담는 함수 기반 인덱스", 강도현은 "그냥 status B-tree"다. 박팀장은 "세 SQL을 하루 합계로 비교하고 하나를 골라라"고 했다.

테이블과 인덱스 ​

  • shipping 배송: 34,908행 · 183블록(블록당 약 191행) · order_id와 1:1 · shipping_id 순으로 쌓였다 · PK (shipping_id)만 있다 · status NOT NULL
  • 이 문제에서는 status를 넷으로 둔다: READY 약 120건 · SHIPPED 약 1,300건 · DELIVERED 약 32,700건 · RETURNED 약 800건 · READY인 배송은 최근 것이라 테이블 끝 블록 한두 개에 모여 있다
  • status에는 히스토그램이 없다(교재 18화의 점검)
  • 실행 횟수: S1 택배사 폴링 하루 8,640번 · S2 대시보드 하루 1,440번 · S3 상태 변경(택배사 콜백) 하루 약 2,000번, 여러 세션이 동시에 보낸다

원본 SQL ​

sql
-- S1 택배사 폴링 (10초마다)
SELECT shipping_id, order_id, address_id
  FROM shipping
 WHERE status = 'READY'
 ORDER BY shipping_id;

-- S2 운영 대시보드 (1분마다)
SELECT status, COUNT(*) FROM shipping GROUP BY status;

-- S3 택배사 콜백
UPDATE shipping
   SET status = :v_status, shipped_date = SYSDATE
 WHERE shipping_id = :v_id;

실행계획 학습용 예시 · status 값과 분포는 문제에 적은 가정 · 비트맵 블록 수는 어림값 ​

xplan
[S1]
------------------------------------------------------------------------------------------
| Id  | Operation           | Name     | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |          |      1 |        |    120 |00:00:00.01 |     183 |
|   1 |  SORT ORDER BY      |          |      1 |   8727 |    120 |00:00:00.01 |     183 |
|*  2 |   TABLE ACCESS FULL | SHIPPING |      1 |   8727 |    120 |00:00:00.01 |     183 |
------------------------------------------------------------------------------------------
   2 - filter("STATUS"='READY')

[S2]
------------------------------------------------------------------------------------------
| Id  | Operation           | Name     | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |          |      1 |        |      4 |00:00:00.01 |     183 |
|   1 |  HASH GROUP BY      |          |      1 |      4 |      4 |00:00:00.01 |     183 |
|   2 |   TABLE ACCESS FULL | SHIPPING |      1 |  34908 |  34908 |00:00:00.01 |     183 |
------------------------------------------------------------------------------------------

문제 ​

  1. 세 제안 (가) status 비트맵 인덱스 (나) READY만 담는 함수 기반 인덱스 (다) status B-tree 인덱스가 S1, S2, S3에 각각 어떤 영향을 주는지 하루 읽는 양과 부작용으로 비교하시오.
  2. 하나를 골라 DDL과 필요한 통계 작업(또는 SQL 변경)을 작성하시오. 고른 이유를 숫자로 설명하시오.
  3. 고른 안에서 S1과 S2의 실행계획이 어떻게 바뀌는지 쓰고, 고르지 않은 두 안이 맞는 경우는 언제인지 설명하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자