Group by 절에 의한 자동정렬이 되지 않는 이유
|
Oracle 10g R2부터 Group By절에 의한 Grouping Column순으로 Sorting되지 않는 문제에 대한 접근 방식입니다. 이러한 문제에 대한 대처방식입니다.
Oracle 10g R2의 “New in-Memory Sort Algorithm”에 따른 문제점 및 개선점 ====================================================================== 2. 성능 개선 효과 3. SORT특징에 따른 개선 효과 ====================================================================== >>>> New in-Memory Sort Algorithm 의 문제점?
====================================================================== >>>> New in-Memory Sort Algorithm 의 문제점인 “GROUP BY”를 기존 방식으로 사용하기 위해서는? Subject: Upgrading from 9i to 10g – Potential Query Tuning Related Issues |
## 실무사례 ##
select r,
s1,
s2,
s3,
s4,
s5,
s6
from (
select ” r,
” s1,
‘총계’ s2,
c3 s3,
decode(c4, null, ‘-‘, 0, ‘-‘, round((c3 – c4)*100/c4, 1)) s4,
c1 s5,
decode(c2, null, ‘-‘, 0, ‘-‘, round((c1 – c2)*100/c2, 1)) s6
from (
select sum(decode(yymm, ‘2006’ ||’04’, amts)) c1,
sum(decode(yymm, ‘2006’-1||’04’, amts)) c2,
sum(decode(yymm, ‘2006’-1||’12’, amts)) c3,
sum(decode(yymm, ‘2006’-2||’12’, amts)) c4
from (
select /*+ index (o kts_m2_x1) */yymm,
sum(decode(‘2’, 1, trade_amt, trade_amt_acm)) amts
from kts_m2 o
where yymm in (‘2006’||’04’,
‘2006’-1||’04’,
‘2006’-1||’12’,
‘2006’-2||’12’)
and ie_gbn = ‘E’
group by yymm ) )
union all
select to_char(rownum),
ctr_cd s1,
kor_name s2,
decode(amt4, null, 0, 0, 0, amt4) s3,
amt3 s4,
decode(amt2, null, 0, 0, 0, amt2) s5,
amt1 s6
from (
select max(a.ctr_cd) ctr_cd,
max(b.kor_name) kor_name,
max(a.s2) amt4,
max(decode(a.s2, null, ‘-‘, decode(a.s1, null, ‘-‘, 0, ‘-‘, round(100*(a.s2-a.s1)/a.s1, 1)))) amt3,
-(-a.s4) amt2,
max(decode(a.s4, null, ‘-‘, decode(a.s3, null, ‘-‘, 0, ‘-‘, round(100*(a.s4-a.s3)/a.s3, 1)))) amt1
from ctr_code b,
(
select /*+ index ( kts_ctr kts_ctr_x1 ) */ctr_cd ctr_cd,
sum(decode(yymm, ‘2006’-2||’12’, decode(‘2’, ‘1’, exp_amt, exp_amt_acm))) s1,
sum(decode(yymm, ‘2006’-1||’12’, decode(‘2’, ‘1’, exp_amt, exp_amt_acm))) s2,
sum(decode(yymm, ‘2006’-1||’04’, decode(‘2’, ‘1’, exp_amt, exp_amt_acm))) s3,
sum(decode(yymm, ‘2006’ ||’04’, decode(‘2’, ‘1’, exp_amt, exp_amt_acm))) s4
from kts_ctr
where yymm in (‘2006′-2||’12’,
‘2006’-1||’12’,
‘2006’-1||’04’,
‘2006’||’04’)
and e_gbn = ‘E’
group by ctr_cd ) a
where a.ctr_cd = b.ctr_cd
group by -a.s4, a.ctr_cd
) )
where 1 = 1
and rownum<=11
8i Plan
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=23 Card=11 Bytes=1K)
1 0 COUNT (STOPKEY)
2 1 VIEW (Cost=23 Card=11 Bytes=1K)
3 2 UNION-ALL
4 3 VIEW (Cost=8 Card=1 Bytes=52)
5 4 FILTER
6 5 SORT (AGGREGATE) (Card=1 Bytes=18)
7 6 VIEW (Cost=8 Card=3 Bytes=54)
8 7 SORT (GROUP BY) (Card=3 Bytes=111)
9 8 CONCATENATION
10 9 INLIST ITERATOR
11 10 TABLE ACCESS (BY INDEX ROWID) OF ‘KSTAT.KTS_M2’ (Cost=3 Card=1 Bytes=37)
12 11 INDEX (RANGE SCAN) OF ‘KSTAT.KTS_M2_X1’ (UNIQUE) (Cost=2 Card=1)
13 9 TABLE ACCESS (BY INDEX ROWID) OF ‘KSTAT.KTS_M2’ (Cost=3 Card=1 Bytes=37)
14 13 INDEX (RANGE SCAN) OF ‘KSTAT.KTS_M2_X1’ (UNIQUE) (Cost=2 Card=1)
15 3 COUNT
16 15 VIEW (Cost=15 Card=10 Bytes=1000)
17 16 SORT (GROUP BY) (Cost=15 Card=10 Bytes=860)
18 17 HASH JOIN (Cost=13 Card=10 Bytes=860)
19 18 VIEW (Cost=11 Card=6 Bytes=330)
20 19 SORT (GROUP BY) (Card=6 Bytes=246)
21 20 CONCATENATION
22 21 TABLE ACCESS (BY INDEX ROWID) OF ‘KSTAT.KTS_CTR’ (Cost=3 Card=1 Bytes=41)
23 22 INDEX (RANGE SCAN) OF ‘KSTAT.KTS_CTR_X1’ (UNIQUE) (Cost=2 Card=1)
24 21 INLIST ITERATOR
25 24 TABLE ACCESS (BY INDEX ROWID) OF ‘KSTAT.KTS_CTR’ (Cost=3 Card=1 Bytes=41)
26 25 INDEX (RANGE SCAN) OF ‘KSTAT.KTS_CTR_X1’ (UNIQUE) (Cost=2 Card=1)
27 18 TABLE ACCESS (FULL) OF ‘KSTAT.CTR_CODE’ (Cost=1 Card=164 Bytes=5K)
총계 284418742503 12 99534827771 11
1 CN 중국 61914983215 24.4 20827196905 12.1
2 US 미국 41342584390 -3.5 13858758704 .9
3 JP 일본 24027437900 10.7 8299955234 9
4 HK 홍콩 15531092215 -14.3 5875131009 25.1
5 TW 대만 10862932443 10.3 3795723262 9.8
6 DE 독일 10303964211 23.6 3254077284 -5.6
7 SG 싱가포르 7406634297 31 2832927989 38.9
8 IN 인디아(인도) 4597836954 26.6 1787342741 32.9
9 GB 영국 5338843555 -3.2 1738720242 7.3
10 AU 호주 3812063148 12.8 1714611147 44.7
10g Plan
0 SELECT STATEMENT Optimizer=RULE (Cost=8 Card=3 Bytes=366)
1 0 COUNT (STOPKEY)
2 1 VIEW (Cost=8 Card=3 Bytes=366)
3 2 UNION-ALL
4 3 VIEW (Cost=3 Card=1 Bytes=52)
5 4 FILTER
6 5 SORT (AGGREGATE) (Card=1 Bytes=21)
7 6 VIEW (Cost=3 Card=2 Bytes=42)
8 7 HASH (GROUP BY) (Card=2 Bytes=74)
9 8 CONCATENATION
10 9 TABLE ACCESS (BY INDEX ROWID) OF ‘KSTAT.KTS_M2’ (TABLE) (Cost=1 Card=1 Bytes=37)
11 10 INDEX (RANGE SCAN) OF ‘KSTAT.KTS_M2_X1’ (INDEX (UNIQUE)) (Cost=1 Card=1)
12 9 INLIST ITERATOR
13 12 TABLE ACCESS (BY INDEX ROWID) OF ‘KSTAT.KTS_M2’ (TABLE) (Cost=1 Card=1 Bytes=37)
14 13 INDEX (RANGE SCAN) OF ‘KSTAT.KTS_M2_X1’ (INDEX (UNIQUE)) (Cost=1 Card=1)
15 3 COUNT
16 15 VIEW (Cost=5 Card=2 Bytes=202)
17 16 HASH (GROUP BY) (Cost=5 Card=2 Bytes=174)
18 17 NESTED LOOPS (Cost=4 Card=2 Bytes=174)
19 18 VIEW (Cost=3 Card=2 Bytes=112)
20 19 HASH (GROUP BY) (Card=2 Bytes=82)
21 20 CONCATENATION
22 21 TABLE ACCESS (BY INDEX ROWID) OF ‘KSTAT.KTS_CTR’ (TABLE) (Cost=1 Card=1 Bytes=41)
23 22 INDEX (RANGE SCAN) OF ‘KSTAT.KTS_CTR_X1’ (INDEX (UNIQUE)) (Cost=1 Card=8)
24 21 INLIST ITERATOR
25 24 TABLE ACCESS (BY INDEX ROWID) OF ‘KSTAT.KTS_CTR’ (TABLE) (Cost=1 Card=1 Bytes=41)
26 25 INDEX (RANGE SCAN) OF ‘KSTAT.KTS_CTR_X1’ (INDEX (UNIQUE)) (Cost=1 Card=8)
27 18 TABLE ACCESS (BY INDEX ROWID) OF ‘KSTAT.CTR_CODE’ (TABLE) (Cost=1 Card=1 Bytes=31)
28 27 INDEX (UNIQUE SCAN) OF ‘KSTAT.CTR_CODE_PK’ (INDEX (UNIQUE)) (Cost=1 Card=1)
총계 284418742503 12 99534827771 11
1 AD 안도라 832819 -34.4 314756 101.1
2 AE 아랍에미리트 연합 2732731530 5.6 905643855 -5.3
3 AF 아프카니스탄 59631357 -22.7 19712121 -3.7
4 AG 안티가 바부다 4588172 70.4 2389520 86.9
5 AI 앙귈라 135659 -43.9 205 -99.6
6 AL 알바니아 6326901 -20.3 7142128 117.6
7 AM 아르메니아 3149597 45 1658169 142.3
8 AN 네덜란드 열도 10756525 50.5 4937642 78.2
9 AO 앙골라 1517394108 -16.4 203785473 -86.1
10 AQ 안타티카 132169 – 0 –
## 해결책 ##
Init.ora 의 _gby_hash_aggregation_enabled=FALSE 의 경우 group by 절 다음에 Single Column 인 경우에는
정상적인 결과가 나오지만 2개 이상의 Column 이 나오는 경우에는 결과가 달라진다. 즉 위 Union all 의
From 절 In-Line View 의 group by –a.s4 의 하나의 Column 으로 결과를 구하면 정상적으로 Sorting 이
되어져서 결과가 나오지만, 예처럼 –a.s4, a.ctr_cd 처럼 Column 을 하나 더 추가하면 결과가 달라진다.
아래와 같이 group by 절 다음에 order by 절을 추가하여 준다.
where a.ctr_cd = b.ctr_cd
group by -a.s4, a.ctr_cd
order by –a.s4,a.ctr_cd ) )
총계 284418742503 12 99534827771 11
1 CN 중국 61914983215 24.4 20827196905 12.1
2 US 미국 41342584390 -3.5 13858758704 .9
3 JP 일본 24027437900 10.7 8299955234 9
4 HK 홍콩 15531092215 -14.3 5875131009 25.1
5 TW 대만 10862932443 10.3 3795723262 9.8
6 DE 독일 10303964211 23.6 3254077284 -5.6
7 SG 싱가포르 7406634297 31 2832927989 38.9
8 IN 인디아(인도) 4597836954 26.6 1787342741 32.9
9 GB 영국 5338843555 -3.2 1738720242 7.3
10 AU 호주 3812063148 12.8 1714611147 44.7
