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

서버 이관 계획서에는 'Data Pump 병렬 8' 한 줄뿐인데, 1년 전 이관 뒤 월마감이 38배 무거워졌던 일이 있다

실전DDL버거103 / 700

상황 ​

버거원 DB가 다음 달 새 서버로 옮겨 간다. 인프라팀 계획서에는 "Data Pump 병렬 8로 내보내고 들여온다. 인덱스는 들여올 때 다시 만든다" 한 줄만 있다. 점검 시간은 토요일 새벽 4시간이다. 박팀장은 이렇게 주문했다. "1년 전 서버 교체 때 ORDER BY 없이 옮겨서 월마감이 41,825블록이 됐다(ACC-002). 그때 미뤄 둔 정렬 재적재를 이번에 같이 한다. 주문과 주문상품을 각각 무엇의 순서로 쌓을지, 절차와 대가, 옮긴 뒤 무엇으로 확인할지 적어 와라."

테이블과 인덱스 ​

  • ORD_RANDOM(운영 주문): 1,000,000행 · 22,414블록 · 1년 전 순서 없이 적재 · ORD_RANDOM_PK (ORD_NO) CF 약 999,950 · ORD_RANDOM_X01 (ORD_DT, ORD_HMS) CF 999,958
  • ORD_ITEM(운영 주문상품): 2,472,717행 · 55,265블록 · (ORD_NO, ITEM_ID) 순으로 쌓여 있다 · ORD_ITEM_PK (ORD_NO, ITEM_ID) CF 약 55,100 · ORD_ITEM_X01 (ORD_DT, ORD_HMS) CF 약 55,200 · 리프 약 9,320
  • ORD_NO는 처음 적재할 때 주문 시각 (ORD_DT, ORD_HMS) 순으로 매긴 번호다 · POS는 주문이 생길 때마다 시각 순으로 INSERT한다
  • 비교용 ORD_ITEM_RANDOM: ORD_ITEM을 무작위 순서로 복제한 개발 서버의 테이블(같은 행 수, 약 55,300블록) · 같은 정의의 X01 CF 약 2,470,000
  • 교재 04화 실측(100만 행): 정렬 CTAS 2.28초 · 인덱스 재생성 1.99초 · 통계 0.87초(NOARCHIVELOG) · 새 서버는 ARCHIVELOG다
  • Data Pump를 병렬로 돌리면 행이 들어가는 순서를 보장하지 않는다

원본 SQL ​

sql
-- 인프라팀 계획: expdp / impdp PARALLEL=8 (테이블 그대로) · 인덱스는 impdp 가 다시 만든다

-- 이관 뒤에도 빨라야 하는 SQL 넷
-- S1 월마감 「가맹점별 주문 건수」
SELECT o.SHOP_NO, COUNT(*) AS ord_cnt
  FROM ORD_RANDOM o
 WHERE o.ORD_DT BETWEEN :v_from AND :v_to
 GROUP BY o.SHOP_NO;
-- S2 「일별 주문 조회」
SELECT o.ORD_NO, o.ORD_HMS, o.SHOP_NO
  FROM ORD_RANDOM o
 WHERE o.ORD_DT = :v_dt
 ORDER BY o.ORD_HMS;
-- S3 「주문 상세」
SELECT i.ITEM_ID, i.ORD_ITEM_QTY
  FROM ORD_ITEM i
 WHERE i.ORD_NO = :v_ord_no;
-- S4 「월 상품 판매」
SELECT i.ITEM_ID, SUM(i.ORD_ITEM_QTY) AS qty
  FROM ORD_ITEM i
 WHERE i.ORD_DT BETWEEN :v_from AND :v_to
 GROUP BY i.ITEM_ID;

실행계획 학습용 예시 · 정렬 전후 숫자는 교재 04화 실측(ORD · ORD_RANDOM) ​

xplan
[S4 · 지금 서버 · 2012년 1월]
-----------------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name         | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |              |      1 |        |     92 |00:00:00.06 |    2690 |
|   1 |  HASH GROUP BY                       |              |      1 |     92 |     92 |00:00:00.06 |    2690 |
|   2 |   TABLE ACCESS BY INDEX ROWID BATCHED| ORD_ITEM     |      1 |  10050 |   102K |00:00:00.05 |    2690 |
|*  3 |    INDEX RANGE SCAN                  | ORD_ITEM_X01 |      1 |  10050 |   102K |00:00:00.01 |     390 |
-----------------------------------------------------------------------------------------------------------------
   3 - access("I"."ORD_DT">=:V_FROM AND "I"."ORD_DT"<=:V_TO)

[측정 · 지금 서버 · Buffers]
  S1 월마감 2012년 1월 (ORD_RANDOM_X01)   41,825      (같은 SQL 을 이관 전 정렬본 ORD 에서 1,086)
  S2 일별 주문 2012-01-01 (1,371건)        1,378      (ORD 에서 39)
  S3 주문 상세 (주문 한 건 2.47줄)          4         (주문 한 건의 줄이 한 블록에 있다)
  S4 월 상품 판매 2012년 1월                2,690      (같은 SQL 을 ORD_ITEM_RANDOM 에서 103,310)

문제 ​

  1. 두 테이블을 각각 무엇의 순서로 쌓아야 하는지 정하시오. 그 순서 하나로 PK와 X01의 CLUSTERING_FACTOR가 함께 좋아지는 이유를 설명하고, ORD_ITEM을 순서 없이 옮기면 S3과 S4가 어떻게 되는지 숫자로 설명하시오.
  2. 새 서버에서 할 이관 절차를 SQL과 DDL로 작성하시오(정렬 적재, 제약과 인덱스, 통계, 확인 쿼리). 정렬 적재의 대가(시간, TEMP, 잠금, 로그)도 적으시오.
  3. 이관 뒤 좋은 CF가 유지되는 조건과 다시 무너지는 경우를 설명하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자