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

매장과 기간만 고르면 40블록 안팎인 판매 건수 타일이 카테고리를 함께 고르면 400블록 넘게 읽는다

중급DDL유통133 / 700

상황 ​

유통 정보계의 BI 도구에는 「판매 건수」 타일이 있다. 매장, 기간, 카테고리를 마음대로 골라 판매 줄 수를 센다. 매장과 기간만 고르면 비트맵 인덱스 두 개로 40블록 안팎이면 끝나는데, 카테고리를 함께 고르면 400블록 넘게 읽는다. 하루 약 2,000번 실행되고 그중 절반이 카테고리를 고른다. 카테고리는 판매상품 사본이 아니라 상품 테이블(CF01)에 있어서, BI 도구는 상품과 조인하는 SQL을 만든다. BI 도구가 만드는 SQL은 고칠 수 없다. 아래는 매장 1003, 2023년 12월, 쉐이크(CTG_NO = 112)다.

테이블과 인덱스 ​

  • DW_SLE_ITM 정보계 판매상품 사본(CF11에 판매일자와 매장을 붙인 파생 테이블): 1,096,708행 · 8,860블록(블록당 약 124행) · SLE_DT · SHP_NO · ITM_NO · SLE_NO · SLE_QTY · SLE_AMT · 매일 02:00에 CTAS로 다시 만들고 낮에는 읽기만 한다 · 날짜순으로 쌓인다
  • 2023년 12월 46,322줄(약 374블록) · 그중 매장 1003이 9,297줄 · 그중 쉐이크 상품 4개가 344줄
  • CF01 정보계 상품(운영에서 밤마다 복제하고 낮에는 읽기만 한다): 109행 · 5블록 · CF01_PK (ITM_NO) · CTG_NO 말단 카테고리 14개 · 쉐이크(112)는 상품 4개
  • 인덱스: 비트맵 BX_DSI_DT (SLE_DT) · BX_DSI_SHP (SHP_NO)(사본을 다시 만든 뒤 만든다) · ITM_NO에는 인덱스가 없다 · STAR_TRANSFORMATION_ENABLED는 기본값(FALSE) · 통계 최신

원본 SQL ​

sql
SELECT COUNT(*) AS line_cnt
  FROM DW_SLE_ITM f, CF01 p
 WHERE p.ITM_NO = f.ITM_NO
   AND p.CTG_NO = :v_ctg
   AND f.SHP_NO = :v_shp
   AND f.SLE_DT BETWEEN :v_from AND :v_to

실행계획 학습용 예시 · 건수와 비트맵 블록 수는 문제에 적은 값 · 사본의 비트맵은 ACC-055와 같은 방식으로 둔다 ​

xplan
------------------------------------------------------------------------------------------------------------
| Id  | Operation                              | Name       | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                       |            |      1 |        |      1 |00:00:00.02 |     414 |
|   1 |  SORT AGGREGATE                        |            |      1 |      1 |      1 |00:00:00.02 |     414 |
|*  2 |   FILTER                               |            |      1 |        |    344 |00:00:00.02 |     414 |
|*  3 |    HASH JOIN                           |            |      1 |    660 |    344 |00:00:00.02 |     414 |
|*  4 |     TABLE ACCESS FULL                  | CF01       |      1 |      8 |      4 |00:00:00.01 |       4 |
|   5 |     TABLE ACCESS BY INDEX ROWID BATCHED| DW_SLE_ITM |      1 |   9200 |   9297 |00:00:00.02 |     410 |
|   6 |      BITMAP CONVERSION TO ROWIDS       |            |      1 |        |   9297 |00:00:00.01 |      36 |
|   7 |       BITMAP AND                       |            |      1 |        |      1 |00:00:00.01 |      36 |
|*  8 |        BITMAP INDEX SINGLE VALUE       | BX_DSI_SHP |      1 |        |      2 |00:00:00.01 |      20 |
|   9 |        BITMAP MERGE                    |            |      1 |        |      1 |00:00:00.01 |      16 |
|* 10 |         BITMAP INDEX RANGE SCAN        | BX_DSI_DT  |      1 |        |     31 |00:00:00.01 |      16 |
------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(:V_FROM<=:V_TO)
   3 - access("P"."ITM_NO"="F"."ITM_NO")
   4 - filter("P"."CTG_NO"=:V_CTG)
   8 - access("F"."SHP_NO"=:V_SHP)
  10 - access("F"."SLE_DT">=:V_FROM AND "F"."SLE_DT"<=:V_TO)

[매장과 기간만 고를 때]  BITMAP CONVERSION COUNT · BITMAP AND(BX_DSI_SHP, BX_DSI_DT) · Buffers 36 · 테이블에 가지 않는다

문제 ​

  1. 카테고리를 고르면 400블록 넘게 읽는 이유를 실행계획의 줄 번호로 설명하시오. 매장과 기간처럼 카테고리도 비트맵으로 겹치지 못하는 이유도 설명하시오.
  2. BI 도구의 SQL을 고치지 않고 카테고리 조건까지 비트맵으로 겹쳐 셀 수 있도록 인덱스를 설계해 DDL을 작성하시오. 고친 실행계획에서 무엇이 달라지는지 설명하시오.
  3. 판매상품 사본에 카테고리 컬럼을 붙이는 방법, ITM_NO 비트맵과 스타 변환을 쓰는 방법과 비교하고, 고른 인덱스를 쓰기 위한 조건과 대가를 설명하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자