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

영수증 조회를 4블록에서 1블록으로 줄이겠다는 판매 테이블 재구성 제안서가 올라왔다

실전DDL유통128 / 700

상황 ​

유통 본사에 외부 컨설턴트의 제안서가 들어왔다. "영수증 조회(SLE_NO = :v)가 판매 SQL 가운데 가장 많이 실행된다. CF10을 SLE_NO 해시 클러스터로 다시 만들면 4블록이 1블록이 된다." 개발 서버에 복사본 CF10_HC를 만들어 재 보니 영수증 조회는 정말 1블록이었다. 박팀장은 "판매 테이블을 쓰는 다른 화면이 어떻게 되는지 하루 전체로 따져서 적어 와라"고 했다. 조민우는 복사본에 날짜 인덱스까지 만들어 재 봤다.

테이블과 인덱스 ​

  • CF10 판매(운영): 500,000행 · 4,583블록 · 판매 날짜순으로 쌓였다 · 2023-06-01의 706건이 13블록에 모여 있다 · 2023년 6월 20,953건
  • 운영 인덱스 CF10_PK (SLE_NO) BLEVEL 2 · IX_CF10_SLE_DT (SLE_DT) BLEVEL 2 · 리프 1,393 · CLUSTERING_FACTOR 9,921(교재 03화 실측)
  • 복사본 CF10_HC: 같은 500,000행을 단일 테이블 해시 클러스터 CF10_HCL(HASHKEYS 600000 · SIZE 80)에 넣었다 · 만들 때 미리 잡은 블록 약 6,000개 · 행은 SLE_NO의 해시 값에 따라 블록에 흩어진다
  • 조민우가 복사본에 만든 CF10_HC_X01 (SLE_DT): 운영 날짜 인덱스와 같은 크기 · CLUSTERING_FACTOR 약 467,000 · 이 인덱스를 만들기 전에 S2는 복사본 FULL 6,012블록이었다
  • 하루 실행 횟수: S1 영수증 조회 약 2,000번(반품, 재출력, 본사 대사) · S2 일별 판매 목록 약 300번 · S3 월별 매장 집계 약 50번 · POS 판매 INSERT 약 700건

원본 SQL ​

sql
-- 제안서의 DDL
CREATE CLUSTER CF10_HCL (SLE_NO VARCHAR2(15)) SIZE 80 HASHKEYS 600000;
CREATE TABLE CF10_HC CLUSTER CF10_HCL (SLE_NO) AS SELECT * FROM CF10;

-- S1 영수증 조회
SELECT SLE_NO, SLE_DT, SLE_HMS, SHP_NO FROM CF10 WHERE SLE_NO = :v_sle_no;

-- S2 일별 판매 목록
SELECT SLE_NO, SLE_HMS, SHP_NO FROM CF10 WHERE SLE_DT = :v_dt ORDER BY SLE_NO;

-- S3 월별 매장 집계
SELECT SHP_NO, COUNT(*)
  FROM CF10
 WHERE SLE_DT BETWEEN :v_from AND :v_to
 GROUP BY SHP_NO;

실행계획 학습용 예시 · 운영 CF10 숫자는 교재 03화 실측 · 복사본 숫자는 해시 클러스터에 행이 고르게 흩어진다고 보고 센 값 ​

xplan
[운영 CF10 · S1]
----------------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |                |      1 |        |      1 |00:00:00.01 |       4 |
|   1 |  TABLE ACCESS BY INDEX ROWID         | CF10           |      1 |      1 |      1 |00:00:00.01 |       4 |
|*  2 |   INDEX UNIQUE SCAN                  | CF10_PK        |      1 |      1 |      1 |00:00:00.01 |       3 |
----------------------------------------------------------------------------------------------------------------
[운영 CF10 · S2 · 2023-06-01]
----------------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |                |      1 |        |    706 |00:00:00.01 |      18 |
|   1 |  SORT ORDER BY                       |                |      1 |    685 |    706 |00:00:00.01 |      18 |
|   2 |   TABLE ACCESS BY INDEX ROWID BATCHED| CF10           |      1 |    685 |    706 |00:00:00.01 |      18 |
|*  3 |    INDEX RANGE SCAN                  | IX_CF10_SLE_DT |      1 |    685 |    706 |00:00:00.01 |       5 |
----------------------------------------------------------------------------------------------------------------
[운영 CF10 · S3 · 2023년 6월]
----------------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |                |      1 |        |      5 |00:00:00.02 |     478 |
|   1 |  HASH GROUP BY                       |                |      1 |      5 |      5 |00:00:00.02 |     478 |
|   2 |   TABLE ACCESS BY INDEX ROWID BATCHED| CF10           |      1 |  20953 |  20953 |00:00:00.02 |     478 |
|*  3 |    INDEX RANGE SCAN                  | IX_CF10_SLE_DT |      1 |  20953 |  20953 |00:00:00.01 |      62 |
----------------------------------------------------------------------------------------------------------------
[복사본 CF10_HC · S1]
----------------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |                |      1 |        |      1 |00:00:00.01 |       1 |
|*  1 |  TABLE ACCESS HASH                   | CF10_HC        |      1 |      1 |      1 |00:00:00.01 |       1 |
----------------------------------------------------------------------------------------------------------------
[복사본 CF10_HC · S2 · 조민우의 X01]
----------------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |                |      1 |        |    706 |00:00:00.02 |     667 |
|   1 |  SORT ORDER BY                       |                |      1 |    685 |    706 |00:00:00.02 |     667 |
|   2 |   TABLE ACCESS BY INDEX ROWID BATCHED| CF10_HC        |      1 |    685 |    706 |00:00:00.02 |     667 |
|*  3 |    INDEX RANGE SCAN                  | CF10_HC_X01    |      1 |    685 |    706 |00:00:00.01 |       5 |
----------------------------------------------------------------------------------------------------------------
[복사본 CF10_HC · S3]
----------------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |                |      1 |        |      5 |00:00:00.05 |    6012 |
|   1 |  HASH GROUP BY                       |                |      1 |      5 |      5 |00:00:00.05 |    6012 |
|*  2 |   TABLE ACCESS FULL                  | CF10_HC        |      1 |  20953 |  20953 |00:00:00.05 |    6012 |
----------------------------------------------------------------------------------------------------------------

문제 ​

  1. 제안서의 S1 숫자가 맞는 이유와, 같은 복사본에서 S2와 S3가 무거워지는 이유를 행이 블록에 놓이는 방식으로 설명하시오. 조민우의 날짜 인덱스가 S2를 18블록으로 돌리지 못한 이유도 설명하시오.
  2. S1, S2, S3의 실행 횟수를 곱해 하루 읽는 양을 운영 CF10과 복사본으로 비교하고, 제안을 받아들일지 판단하시오. 판단에 맞는 SQL과 DDL을 작성하시오.
  3. 해시 클러스터의 다른 제약이 판매 테이블에 어떤 영향을 주는지 설명하고, 해시 클러스터가 맞는 테이블의 조건을 정리하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자