Skip to content
튜닝 연습파티션
PART-030

매장별로 나눴다는 판매 테이블인데 매장마다 조회 일량이 두 배씩 차이 난다

기초SELECT유통405 / 700

상황 ​

유통 본사는 지난해 매장 포털을 열면서 판매를 "매장별로" 나눈 복사본 CF10_H를 만들었다. 매장 직원은 자기 매장의 한 달 판매를 일자별로 본다(하루 수천 번). 1002번 매장은 0.02초인데 다른 네 매장은 0.04초쯤 걸린다. 당시 설계 메모에는 "매장별 분산 → HASH. 칸 수는 2의 거듭제곱 규칙대로 4." 한 줄만 남아 있다.

테이블과 인덱스 ​

  • CF10_H 판매(파티션 복사본, 문제 설정): CF10 500,000행을 PARTITION BY HASH (SHP_NO) PARTITIONS 4로 나눠 CTAS로 지었다. 칸 이름은 SYS_P2201 ~ SYS_P2204다.
  • 판매가 있는 매장은 다섯 곳(SHP_NO 1001 ~ 1005, NUMBER)이고 매장마다 약 100,000행, 약 917블록이다. SLE_DT는 VARCHAR2(8)이다. 매장 하나의 한 달 판매는 약 4,200건이다.
  • 인덱스는 CF10_H_PK (SLE_NO) GLOBAL뿐이다. 통계는 최신이다.
  • 내년에 1006번 매장이 문을 연다. 매장이 문을 닫으면 그 매장의 판매를 따로 보관하고 지워야 한다.

원본 SQL ​

sql
CREATE TABLE CF10_H
PARTITION BY HASH (SHP_NO) PARTITIONS 4
AS SELECT * FROM CF10;

-- 매장 포털 「매장 일별 판매」 (:v_shp = 1003, :v_from = '20230601', :v_to = '20230630')
SELECT SLE_DT, COUNT(*) AS sle_cnt
  FROM CF10_H
 WHERE SHP_NO = :v_shp
   AND SLE_DT BETWEEN :v_from AND :v_to
 GROUP BY SLE_DT
 ORDER BY SLE_DT;

실행계획 학습용 예시 ​

xplan
[:v_shp = 1003]
---------------------------------------------------------------------------------------------------------------
| Id  | Operation                | Name   | Starts | E-Rows | A-Rows |      A-Time | Buffers | Pstart | Pstop |
---------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |        |      1 |        |     30 | 00:00:00.04 |    1840 |        |       |
|   1 |  SORT GROUP BY           |        |      1 |     30 |     30 | 00:00:00.04 |    1840 |        |       |
|*  2 |   FILTER                 |        |      1 |        |   4213 | 00:00:00.04 |    1840 |        |       |
|   3 |    PARTITION HASH SINGLE |        |      1 |   2096 |   4213 | 00:00:00.04 |    1840 |    KEY |   KEY |
|*  4 |     TABLE ACCESS FULL    | CF10_H |      1 |   2096 |   4213 | 00:00:00.04 |    1840 |    KEY |   KEY |
---------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(:V_FROM<=:V_TO)
   4 - filter(("SHP_NO"=:V_SHP AND "SLE_DT">=:V_FROM AND "SLE_DT"<=:V_TO))

  (실행 때 고른 칸 — 1번 SYS_P2201)

[:v_shp = 1002]  같은 모양 · 2번 칸 SYS_P2202 · A-Rows 4,188 · Buffers 921

[USER_TAB_PARTITIONS · 칸마다 든 매장 (SELECT DISTINCT SHP_NO FROM CF10_H PARTITION (…))]
  PARTITION_NAME   NUM_ROWS   BLOCKS   든 매장
  SYS_P2201         200,180    1,836   1001 · 1003
  SYS_P2202          99,950      917   1002
  SYS_P2203               0        0   —
  SYS_P2204         199,870    1,833   1004 · 1005

문제 ​

  1. 매장마다 일량이 두 배씩 다른 까닭을 파티션 통계와 해시 파티션의 원리로 설명하시오.
  2. 이 테이블에 맞는 파티션 방식을 골라 DDL을 쓰고, 1003번 매장 조회가 몇 블록을 읽을지와 1006번 매장이 문을 열 때 할 일을 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자