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

같은 한 달 조회가 ORD_LIST에서는 1,980블록인데 ORD_LIST_HASH에서는 9,039블록이다

중급DDL버거407 / 700

상황 ​

버거 본사 분석 DB에는 같은 주문 100만 행이 ORD_LIST와 ORD_LIST_HASH 두 모양으로 있다. 분석 화면은 대부분 ORD_LIST_HASH를 쓴다. 분석 DB 공간이 Free의 12GB 한도에 거의 차서, 이번에 둘 중 하나를 정리하고 남길 테이블의 모양을 정하기로 했다. ORD_LIST_HASH의 해시 8조각은 누가 왜 나눴는지 기록이 없다. 이관 스크립트에는 빈 테이블을 먼저 만들고 INSERT /*+ APPEND PARALLEL(ORL 4) */로 채운 흔적만 남아 있다.

테이블과 인덱스 ​

  • ORD_LIST 주문(교재 14화): PARTITION BY LIST (ORD_YM) 25칸(P201201 ~ P201312과 빈 P_DEFAULT) · 세그먼트 24개 · 384MB. 칸 하나 FULL ≈ 1,980블록(데이터 약 971블록과 빈 블록 약 1,006블록)이다.
  • ORD_LIST_HASH 주문(교재 14화): PARTITION BY LIST (ORD_YM) 25칸 × SUBPARTITION BY HASH (ORD_NO) SUBPARTITIONS 8 · 세그먼트 192개 · 3,072MB. 서브파티션 하나는 데이터 약 121블록에 빈 블록 약 1,006블록이다.
  • 두 테이블 모두 빈 테이블에 APPEND로 채웠다. 이 버전은 파티션과 서브파티션의 첫 익스텐트를 8MB(1,024블록)로 잡는다.
  • 분석 DB에서 이 테이블을 쓰는 SQL은 셋이다. ① 「월 매장 실적」 ORD_YM 한 달 전체(하루 수십 번) ② 「매장 월 주문」 ORD_YM과 SHOP_NO(하루 수백 번) ③ 「영수증 조회」 ORD_NO와 ORD_YM(하루 수십 번)
  • 주문상품 쪽 해시 복사본(ORD_ITEM_LIST_HASH)은 공간이 모자라 지웠다. 분석 DB는 밤에 한 번 적재한다.
  • LOCAL 인덱스 ORD_LIST_HASH_PK (ORD_NO, ORD_YM)가 있다. 통계는 최신이다.

원본 SQL ​

sql
-- ① 「월 매장 실적」 (:v_ym = '201206')
SELECT SHOP_NO, COUNT(*) AS ord_cnt
  FROM ORD_LIST_HASH
 WHERE ORD_YM = :v_ym
 GROUP BY SHOP_NO;

실행계획 실측 · 교재 14화 ​

xplan
[① · ORD_LIST_HASH]
---------------------------------------------------------------------------------------------------------------------
| Id  | Operation               | Name          | Starts | E-Rows | A-Rows |      A-Time | Buffers | Pstart | Pstop |
---------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |               |      1 |        |    200 | 00:00:00.12 |    9039 |        |       |
|   1 |  HASH GROUP BY          |               |      1 |    200 |    200 | 00:00:00.12 |    9039 |        |       |
|   2 |   PARTITION LIST SINGLE |               |      1 |  41040 |  41040 | 00:00:00.10 |    9039 |    KEY |   KEY |
|   3 |    PARTITION HASH ALL   |               |      1 |  41040 |  41040 | 00:00:00.10 |    9039 |      1 |     8 |
|   4 |     TABLE ACCESS FULL   | ORD_LIST_HASH |      8 |  41040 |  41040 | 00:00:00.09 |    9039 |    KEY |   KEY |
---------------------------------------------------------------------------------------------------------------------

[① · ORD_LIST (같은 조건)]
----------------------------------------------------------------------------------------------------------------
| Id  | Operation               | Name     | Starts | E-Rows | A-Rows |      A-Time | Buffers | Pstart | Pstop |
----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |          |      1 |        |    200 | 00:00:00.05 |    1980 |        |       |
|   1 |  HASH GROUP BY          |          |      1 |    200 |    200 | 00:00:00.05 |    1980 |        |       |
|   2 |   PARTITION LIST SINGLE |          |      1 |  41040 |  41040 | 00:00:00.03 |    1980 |    KEY |   KEY |
|   3 |    TABLE ACCESS FULL    | ORD_LIST |      1 |  41040 |  41040 | 00:00:00.02 |    1980 |    KEY |   KEY |
----------------------------------------------------------------------------------------------------------------

[③ 「영수증 조회」 · ORD_LIST_HASH · :ord_no = 777777, :ord_ym = '201307']
-------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name             | Starts | E-Rows | A-Rows |      A-Time | Buffers | Pstart | Pstop |
-------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |                  |      1 |        |      1 | 00:00:00.01 |       3 |        |       |
|   1 |  PARTITION LIST SINGLE               |                  |      1 |      1 |      1 | 00:00:00.01 |       3 |    KEY |   KEY |
|   2 |   PARTITION HASH SINGLE              |                  |      1 |      1 |      1 | 00:00:00.01 |       3 |    KEY |   KEY |
|   3 |    TABLE ACCESS BY LOCAL INDEX ROWID | ORD_LIST_HASH    |      1 |      1 |      1 | 00:00:00.01 |       3 |    KEY |   KEY |
|*  4 |     INDEX UNIQUE SCAN                | ORD_LIST_HASH_PK |      1 |      1 |      1 | 00:00:00.01 |       2 |    KEY |   KEY |
-------------------------------------------------------------------------------------------------------------------------------------

   4 - access("ORD_NO"=:ORD_NO AND "ORD_YM"=:ORD_YM)

[세그먼트 · USER_SEGMENTS]
  ORD_LIST          24개      384 MB
  ORD_LIST_HASH    192개    3,072 MB

문제 ​

  1. ①이 ORD_LIST_HASH에서 4.6배 읽는 까닭을 실행계획의 두 PARTITION 줄과 세그먼트 수로 설명하시오.
  2. 해시 서브파티션이 ① ~ ③ 가운데 어느 SQL에 도움이 되는지 판단하고, 이 분석 DB에 맞게 남길 테이블을 다시 짓는 DDL을 쓰시오.
  3. 다시 지은 뒤 ①의 블록 수와 공간을 어림하고, 해시 서브파티션을 다시 고려해야 할 조건을 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자