[운영 종료] TmaxTibero Tech Blog

티맥스티베로 공식 블로그는 https://tmaxtibero.blog/ 로 이전되었습니다.

티맥스티베로 공식 블로그 이전 자세히보기

튜닝

[Tibero] SQL Tuning (13)

TmaxTiberotech 2023. 6. 13. 14:35

Tuning 사례

3. JOIN 순서/방법

3.1. 힌트 추가

EXAMPLE

SELECT …
FROM COLLECTUNIT_MISSING A, COLLECTUNIT_PREDICTION B
WHERE A.ANALYSISDATE = ? AND B.ANALYSISDATE(+) = ? AND B.COLLECTUNITTYPE(+) = ?
AND A.MISSINGCNT > 5
AND A.BUSROUTEID = B.BUSROUTEID (+)
AND A.COLLECTUNITID = B.COLLECTUNITID(+)
AND A.MISSTYPEBIS = '1‘
  2072 hash join (reverse left outer) (et=66499, cr=0, cu=0, co=42873, cpu=4, ro=23782233)
29119 partition iterator(ALL PART) (PS:1, PE:25) (et=72, cr=0, cu=0, co=4749, cpu=0, ro=16409)
29119 table access (rowid) COLLECTUNIT_PREDICTION(8465) (et=8583873463831278, cr=296, cu=0, co=4749, cpu=0, ro=16409)
29119 filter (et=3586, cr=0, cu=0, co=302, cpu=0, ro=16409)
33697 index (range scan) COLLECTUNIT_PREDICTION_PK(8491) (et=3814, cr=354, cu=0, co=301, cpu=0, ro=32818)
  2072 partition iterator(ALL PART) (PS:1, PE:22) (et=132, cr=0, cu=0, co=37181, cpu=2, ro=1366144)
  2072 table access (full) COLLECTUNIT_MISSING(3292) (et=8583873470045409, cr=87152, cu=230, co=37181, cpu=2, ro=1366144)

Join에서는 Left row 개수가 적을수록 처리가 용이합니다.

위 예제는 Left가 right 보다 row수가 많이 생성되므로 Leading 힌트를 사용합니다.

 

SELECT /*+ LEADING(A B) */
FROM COLLECTUNIT_MISSING A, COLLECTUNIT_PREDICTION B
WHERE A.ANALYSISDATE = ? AND B.ANALYSISDATE(+) = ? AND B.COLLECTUNITTYPE(+) = ?
AND A.MISSINGCNT > 5
AND A.BUSROUTEID = B.BUSROUTEID (+)
AND A.COLLECTUNITID = B.COLLECTUNITID(+)
AND A.MISSTYPEBIS = '1‘

3.2. 힌트 반영 안되는 경우

Join별 알고리즘 특성을 파악해 알맞은 join을 사용합니다.

Join 별 알고리즘 특성

INDEX JOIN

  • NESTED LOOP의 index 버전입니다.
  • JOIN 왼쪽에서 row가 많이 올라올수록 loop 횟수가 증가합니다.
  • 왼쪽 row가 적게 올라올때 효과적입니다.

HASH JOIN

  • 양쪽 row가 많이 올라올때 INDEX JOIN보다 효과적입니다.

EXAMPLE

SELECT /*+ USE_HASH(A B) */… FROM – USE_HASH 힌트 반영이 안됩니다.
(SELECT BUSROUTEID, POINT_ID, MIN(ROUTEUNITSEQ) SEQ1, MAX(ROUTEUNITSEQ) SEQ3
FROM (…
UNION ALL
SELECT BUSROUTEID, ROUTEUNITSEQ+1 ROUTEUNITSEQ, ENDPOINTID POINT_ID
FROM BUSROUTE_INFOUNIT A,
BUS_INFOUNIT B
WHERE A.INFOUNITID = B.INFOUNITID)
GROUP BY BUSROUTEID, POINT_ID) A,
(SELECT BUSROUTEID, ROUTEUNITSEQ+1 ROUTEUNITSEQ, POINT_ID
FROM (…
UNION ALL
SELECT BUSROUTEID, ROUTEUNITSEQ, ENDPOINTID POINT_ID
FROM BUSROUTE_INFOUNIT A,
BUS_INFOUNIT B
WHERE A.INFOUNITID = B.INFOUNITID)) B
WHERE A.BUSROUTEID = B.BUSROUTEID(+)
AND A.POINT_ID = B.POINT_ID(+)
AND A.SEQ1 < B.ROUTEUNITSEQ(+)
AND A.SEQ3 > B.ROUTEUNITSEQ(+)

 

​위 예제는 적용한 힌트가 반영되지 않고 Index Join으로 처리되고 있습니다.

이때 'Cardinality 힌트'를 사용해 Hash join을 유도합니다.

 

SELECT … FROM
(SELECT BUSROUTEID, POINT_ID, MIN(ROUTEUNITSEQ) SEQ1, MAX(ROUTEUNITSEQ) SEQ3
FROM (…
UNION ALL
SELECT /*+ CARD(A B 10000000) */ BUSROUTEID, ROUTEUNITSEQ+1 ROUTEUNITSEQ, ENDPOINTID POINT_ID
FROM BUSROUTE_INFOUNIT A,
BUS_INFOUNIT B
WHERE A.INFOUNITID = B.INFOUNITID)
GROUP BY BUSROUTEID, POINT_ID) A,
(SELECT BUSROUTEID, ROUTEUNITSEQ+1 ROUTEUNITSEQ, POINT_ID
FROM (…
UNION ALL
SELECT /*+ CARD(A B 10000000) */ BUSROUTEID, ROUTEUNITSEQ, ENDPOINTID POINT_ID
FROM BUSROUTE_INFOUNIT A,
BUS_INFOUNIT B
WHERE A.INFOUNITID = B.INFOUNITID)) B
WHERE A.BUSROUTEID = B.BUSROUTEID(+)
AND A.POINT_ID = B.POINT_ID(+)
AND A.SEQ1 < B.ROUTEUNITSEQ(+)
AND A.SEQ3 > B.ROUTEUNITSEQ(+)

 

SELECT …
FROM COLLECTUNIT_MISSING A, COLLECTUNIT_PREDICTION B
WHERE A.ANALYSISDATE = ? AND B.ANALYSISDATE(+) = ? AND B.COLLECTUNITTYPE(+) = ?
AND A.MISSINGCNT > 5
AND A.BUSROUTEID = B.BUSROUTEID
AND A.COLLECTUNITID = B.COLLECTUNITID
AND A.MISSTYPEBIS = '1‘
  2072 hash join (reverse left outer) (et=66499, cr=0, cu=0, co=42873, cpu=4, ro=23782233)
29119 partition iterator(ALL PART) (PS:1, PE:25) (et=72, cr=0, cu=0, co=4749, cpu=0, ro=16409)
29119 table access (rowid) COLLECTUNIT_PREDICTION(8465) (et=8583873463831278, cr=296, cu=0, co=4749, cpu=0, ro=16409)
29119 filter (et=3586, cr=0, cu=0, co=302, cpu=0, ro=16409)
33697 index (range scan) COLLECTUNIT_PREDICTION_PK(8491) (et=3814, cr=354, cu=0, co=301, cpu=0, ro=32818)
  2072 partition iterator(ALL PART) (PS:1, PE:22) (et=132, cr=0, cu=0, co=37181, cpu=2, ro=1366144)
  2072 table access (full) COLLECTUNIT_MISSING(3292) (et=8583873470045409, cr=87152, cu=230, co=37181, cpu=2, ro=1366144)

4. 통계 분포도

히스토그램 최대, 최소값 사이가 아닌 값이 조건문인 경우 입니다.

EXAMPLE

SELECT DISTINCT BUSROUTEID RID, COLLECTUNITID CID, COLLECTUNITLENGTH CLEN,
COLLECTUNITTYPE CTYPE
FROM COLLECTUNIT_PREDICTION a
WHERE ANALYSISDATE = TO_DATE('2013/01/25 05:00:00','YYYY/MM/DD HH24:MI:SS')
AND COLLECTUNITTYPE = 'U‘
    646 partition iterator(ALL PART) (PS:1, PE:56) (et=68, cr=0, cu=0, co=4, cpu=0, ro=1)
    646  filter (et=2236, cr=0, cu=0, co=4, cpu=0, ro=1)
29765  index (range scan) COLLECTUNIT_PREDICTION_PK(8491) (et=6985, cr=278, cu=0, co=4, cpu=0, ro=1)

 

 

위 예제는 최대값보다 큰 영역이기에 1개를 예측했으나 실제는 많은 수가 존재합니다.

아래 방법을 참고해 해결합니다.

Optimizer의 영역 외 값 계산 기능

히스토그램에는 (1~100) 사이 값만 있어도 101에도 존재할 수 있음을 가정합니다.

_OPT_BOUND_SELEC_ADJUST_DEGREE

영역 바깥의 값에 대한 고려를 위한 기울기값으로 기본값은 0 입니다.

문제 발생시 100으로 설정을 변경합니다.

 

☞[Tibero] SQL Tuning (14) 에서 계속됩니다.​

 

 

'튜닝' 카테고리의 다른 글

[Tibero] SQL Tuning (14)  (0) 2023.06.14
[Tibero] SQL Tuning (12)  (0) 2023.06.13
[Tibero] SQL Tuning (11)  (0) 2023.06.12
[Tibero] SQL Tuning (10)  (0) 2023.06.09
[Tibero] SQL Tuning (9)  (0) 2023.06.08