현상
INDEX SCAN과 TABLE FULL SCAN 결과 값이 다른 현상에 대해 설명합니다.
-- 1. TABLE FULL SCAN 결과 (정상)
set linesize 150
set autot on exp stat planstat
SELECT /*+ FULL(A) */ DISTINCT LGV_CD
FROM TLGSBT003A A
WHERE MNG_YM BETWEEN '202303' AND '202412'
AND EPD_BGT_DAT_CL_CD = '2'
ORDER BY 1 ;
LGV_CD
------
1
2
3
4
5
6
7
7 rows selected.
SQL ID: dddtk8s1w4wkr
Child number: 18014398509486028
Plan hash value: 2188397784
Execution Plan
----------------------------------------------------------------------------
1 DISTINCT (SORT) (Cost:207, %%CPU:0, Rows:3)
2 PARTITION RANGE (SUBSET PART) (Cost:207, %%CPU:0, Rows:3) (PS:2, PE:3)
3 TABLE ACCESS (FULL): TLGSBT003A (Cost:207, %%CPU:0, Rows:3)
Predicate Information
---------------------------------------------------------------------------
3 - filter: ("A"."MNG_YM" >= '202303') AND ("A"."EPD_BGT_DAT_CL_CD" = '2')
AND ("A"."MNG_YM" <= '202412') (0.266 * 0.375 * 1.000)
Execution Stat
---------------------------------------------------------------------------
1 DISTINCT (SORT) (Time:.11 ms, Rows:7, Starts:1)
2 PARTITION RANGE (SUBSET PART) (Time:0. ms, Rows:12, Starts:1)
3 TABLE ACCESS (FULL): TLGSBT003A (Time:.19 ms, Rows:12, Starts:2)
-- 2. INDEX SCAN 결과 (비정상, RANGE SCAN, SKIP SCAN 모두 결과 동일)
set linesize 150
set autot on exp stat planstat
SELECT DISTINCT LGV_CD
FROM TLGSBT003A A
WHERE MNG_YM BETWEEN '202303' AND '202412'
AND EPD_BGT_DAT_CL_CD = '2'
ORDER BY 1 ;
LGV_CD
------
1
2
3
4
5
6
7
1
2
3
4
5
12 rows selected.
SQL ID: 28z3haqk8g6r3
Child number: 18014398509486029
Plan hash value: 2782779433
Execution Plan
---------------------------------------------------------------------------------------
1 PARTITION RANGE (SUBSET PART) (Cost:2, %%CPU:0, Rows:3) (PS:2, PE:3)
2 DISTINCT (Cost:2, %%CPU:0, Rows:3)
3 FILTER (Cost:2, %%CPU:0, Rows:3)
4 INDEX (RANGE SCAN): TLGSBT003A_PK (Cost:2, %%CPU:0, Rows:12)
Predicate Information
-------------------------------------------------------------------------------------
3 - filter: ("A"."MNG_YM" >= '202303') AND ("A"."MNG_YM" <= '202412') (0.266 * 1.000)
4 - access: ("A"."EPD_BGT_DAT_CL_CD" = '2') (0.375)
Execution Stat
-------------------------------------------------------------------------------------
1 PARTITION RANGE (SUBSET PART) (Time:.01 ms, Rows:12, Starts:1)
2 DISTINCT (Time:.01 ms, Rows:12, Starts:2)
3 FILTER (Time:.01 ms, Rows:12, Starts:2)
4 INDEX (RANGE SCAN): TLGSBT003A_PK (Time:.05 ms, Rows:12, Starts:2)
SQL
복사
원인
정상 플랜에서는 DISTINCT를 수행하기 전에 distinct 키 LGV_CD로 데이터를 정렬해 주어야 합니다.
실제로 table scan으로 플랜이 풀린 경우에는, 정렬 이후 DISTINCT를 수행하게끔 DISTINCT(SORT)로 풀린 것을 확인하실 수 있습니다.
그러나 index scan으로 풀리는 경우, DISTINCT(SORT)로 풀거나 DISTINCT 이전에 order by를 추가하지 않아 결과값 오류를 유발하고 있었습니다.
해결
패치를 적용해 해결합니다. (적용패치: 293764b)
주의
티맥스티베로에서 제공하는 기술지원을 통해 패치를 적용합니다.
참고
index_desc 힌트를 사용하는 것으로도 우회 가능합니다.
SELECT /*+ INDEX_DESC (A) */ DISTINCT LGV_CD
FROM TLGSBT003A A
WHERE MNG_YM BETWEEN '202303' AND '202412'
AND EPD_BGT_DAT_CL_CD = '2'
ORDER BY 1 ;
SQL
복사