Upload
dillian
View
57
Download
1
Embed Size (px)
DESCRIPTION
사례 1. 년 / 월이 분리된 경우에도 인덱스 사용. 인덱스정보 TAB_A : TAB_A_X1 : YY + MM + DD + SALE_NO QUERY. SELECT A.YY || A.MM, DEPT, SUM(SALE_QTY) FROM TAB_A A WHERE A.YY || A.MM BETWEEN '9410' AND '9504' GROUP BY A.YY || A.MM, DEPT ;. 개선된 QUERY. SELECT A.YY || A.MM, DEPT, SUM(SALE_QTY) - PowerPoint PPT Presentation
Citation preview
DB 기술자문팀 1
SQLTuning
SQLTuning 사례 1. 년 / 월이 분리된 경우에도 인덱스 사용
인덱스정보인덱스정보TAB_A : TAB_A_X1 : YY + MMYY + MM + DD + SALE_NO
QUERYQUERYSELECT A.YY || A.MM, DEPT, SUM(SALE_QTY) FROM TAB_A A
WHERE A.YY || A.MM BETWEEN '9410' AND '9504'A.YY || A.MM BETWEEN '9410' AND '9504' GROUP BY A.YY || A.MM, DEPT ;
개 선 된 개 선 된 QUERYQUERY SELECT A.YY || A.MM, DEPT, SUM(SALE_QTY)
FROM TAB_A A
WHERE (A.YY = '94' AND A.MM BETWEEN '10' AND '12')(A.YY = '94' AND A.MM BETWEEN '10' AND '12')
OR (A.YY = '95' AND A.MM BETWEEN '01' AND '04')OR (A.YY = '95' AND A.MM BETWEEN '01' AND '04')
GROUP BY A.YY || A.MM, DEPT ;
DB 기술자문팀 2
SQLTuning
SQLTuning
SELECT NVL (DEPTNO, ' ')
INTO :B1
FROM EMP
WHERE EMPNO = :B2 EMPNO = :B2 ;
사례 2. BINDING 변수의 인덱스 사용 확인
테이블 정보테이블 정보
인덱스 정보인덱스 정보 EMP : EMP_EMPNO_PK :
EMPNO
QUERYQUERY ROWS EXECUTION PLANROWS EXECUTION PLAN------ ----------------------------------------------
0 SELECT STATEMENTSELECT STATEMENT1314813148 TABLE ACCESS (TABLE ACCESS (BY ROWIDBY ROWID) OF 'EMP') OF 'EMP' 00 INDEX (INDEX (RANGE SCANRANGE SCAN) OF 'EMP_EMPNO_PK' ) OF 'EMP_EMPNO_PK' ((UNIQUEUNIQUE))
1) Dynamic SQL1) Dynamic SQL 에서 주의에서 주의2) HOST 2) HOST 변수 선언에서 주의변수 선언에서 주의
EMPEMP
# * EMPNO VARCHAR2(5) ENAME VARCHAR2(20) DEPTNO VARCHAR2(5)
( 총 로우 수 :13,148)
DB 기술자문팀 3
SQLTuning
SQLTuning
SELECT H14_ACNT_CODE, H14_GWANLI_CODE, H14_MAGAM_YY, H14_MAGAM_MM, H14_GUBUN, H14_C_AMT, H14_D_AMT FROM FH14 WHERE H14_MAGAM_YY = :B0 AND H14_GUBUN = :B1
ORDER BY H14_ACNT_CODE, H14_GWANLI_CODEORDER BY H14_ACNT_CODE, H14_GWANLI_CODE ;
사례 3. ORDER BY 절에서도 인덱스 사용
인덱스정보인덱스정보
FH14 : IFH14_KEY1 : H14_ACNT_CODE + H14_GWANLI_CODEH14_ACNT_CODE + H14_GWANLI_CODE + H14_MAGAM_YY
+ H14_MAGAM_MM + H14_GUBUN QUERYQUERY
ROWS EXECUTION PLANROWS EXECUTION PLAN ---- ----------------------------------------------- 0 SELECT STATEMENT HINT: CHOOSE 5743 TABLE ACCESS (BY ROWID) OF 'FH14'168188 INDEX (RANGE SCAN) OF 'IFH14_KEY1' (UNIQUE)
Order By 에 의한SORT Plan 이 없는 이유 ?
전제 : 적어도 하나이상의 컬럼이 NOT NULL
DB 기술자문팀 4
SQLTuning
SQLTuning
SELECT STOCK_Q FROM GFLM600 WHERE IO_DATEIO_DATE = (SELECT MAX(IO_DATE)MAX(IO_DATE) FROM GFLM600 WHERE CAR_CODE = :VALUE1 AND BOX_CODE = :VALUE2) ;
사례 4. MAX 값의 처리
인덱스정보인덱스정보GFLM600 : GFLM600_PK : CAR_CODE + BOX_CODE + IO_DATE
QUERYQUERY두 두 SUB-QuerySUB-Query 의 차이는 의 차이는 ??
SELECT STOCK_Q FROM GFLM600 A WHERE IO_DATE = (SELECT MAX(IO_DATE) FROM GFLM600 B WHERE B.CAR_CODE = :VALUE1 AND B.BOX_CODE = :VALUE2 AND A.CAR_CODE = B.CAR_CODE AND A.CAR_CODE = B.CAR_CODE AND A.BOX_CODE = B.BOX_CODE ) ;AND A.BOX_CODE = B.BOX_CODE ) ;
원하는 결과 나오지 않음
DB 기술자문팀 5
SQLTuning
SQLTuning
SELECT /*+ INDEX_DESC(A GFLM600_PK) *//*+ INDEX_DESC(A GFLM600_PK) */ STOCK_Q FROM GFLM600 A WHERE CAR_CODE = :VALUE1 AND BOX_CODE = :VALUE2 AND ROWNUM = 1 ;AND ROWNUM = 1 ;
SELECT SUBSTR (MAX (IO_DATE || STOCK_Q), 9, 4)SUBSTR (MAX (IO_DATE || STOCK_Q), 9, 4) FROM GFLM600 WHERE CAR_CODE = :VALUE1 AND BOX_CODE = :VALUE2;
사례 4. MAX 값의 처리
해결 방안해결 방안 1) 1) 역순 인덱스 사용역순 인덱스 사용
2) SUBSTR 2) SUBSTR 사용 사용 (( 인덱스 없을 때인덱스 없을 때 ))
DB 기술자문팀 6
SQLTuning
SQLTuning 사례 5. 불필요한 DUAL
인덱스정보인덱스정보PATN : PATN_PK : ID + DAT (PRIMARY KEY)PATN : PATN_IDX1 : DEPT + GUBUNPATN : PATN_IDX2 : WARD + GUBUN
QUERYQUERY
SELECT ID, DEPT, WARD, ROOM INTO :B1, :B2, :B3, :B4 FROM PATN WHERE WARD = :C1 AND NVL(DAT,'999999') >= TO_CHAR(SYSDATE, 'YYMMDD') TO_CHAR(SYSDATE, 'YYMMDD') ORDER BY DEPT, ROOM ;
SELECT ID, DEPT, WARD, ROOM INTO :B1, :B2, :B3, :B4 FROM PATN WHERE WARD = :C1 AND NVL(DAT, '999999') >= (SELECT TO_CHAR(SYSDATE, 'YYMMDD')SELECT TO_CHAR(SYSDATE, 'YYMMDD') FROM SYS.DUALFROM SYS.DUAL) ORDER BY DEPT, ROOM ;
개선된개선된 QUERYQUERY
DB 기술자문팀 7
SQLTuning
SQLTuning
A 110 10
A 111 11
A 112A 112 5
COL1 COL2 ROWID
COL2 COL1 ROWID
INDEX ( COL1 + COL2 ) INDEX ( COL2 + COL1 )
결합 인덱스의 처리 범위 ( 둘 다 '=' 로 쓰인 경우 )
110 A 10
110 B 41
110 C 57
111 A 11
111 B 39
111 C 76
112 A112 A 5
112 B 73
112 C 89
113 A 18 114 A 22
A 115 23
A 113 18
A 114 22
A 116 29
A 117 25
A 118 26
B 110 41
B 111 39
SELECT * FROM TAB1 SELECT * FROM TAB1 WHERE COL1 WHERE COL1 = = 'AA' (( 분포도가 넓다분포도가 넓다 )) AND COL2 AND COL2 == '112112' (( 분포도가 좁다분포도가 좁다 ))
DB 기술자문팀 8
SQLTuning
SQLTuning
A 110 10
A 111A 111 11
A 112A 112 5
A 115 23
A 113A 113 18
A 114 22
A 116 29
A 117 25
A 118 26
B 110 41
B 111 39
COL1 COL2 ROWID
COL2 COL1 ROWID
SELECT * FROM TAB1 SELECT * FROM TAB1 WHERE COL1 WHERE COL1 = = 'AA'AND COL2 AND COL2 BETWEENBETWEEN '111111' AND AND '113113'
INDEX ( COL1 + COL2 ) INDEX ( COL2 + COL1 )
결합 인덱스의 처리 범위 ( 둘 다 '=' 로 안 쓰인 경우 )
110 B 41
110 C 57
111 A111 A 11
111111 B 39
111 111 C 76
112 A112 A 5
112112 B 73
112 112 C 89
113 A113 A 18 113113 B 44
114 A 22
DB 기술자문팀 9
SQLTuning
SQLTuning
SELECT ACT_CODE, PART_MODEL_CODE, PART_CHAR_CODE, PART_SPEC, PART_ROUT_CODE, ORDERNO, ITEMNO, DIN_ACT_MH,
WORK_ORDER_NO, S_MODEL_NO, DRAW_NO, MATR_STATUS, WORK_ORDER_DATE,
ROWIDFROM S_WORKPLANWHERE WORK_ORDER_DATE WORK_ORDER_DATE LIKELIKE :B1 || '%' :B1 || '%' AND DEPT_CODE = :B2AND DEPT_CODE = :B2 AND GROUP_CODE = :B3AND GROUP_CODE = :B3ORDER BY ACT_CODE ;
사례 6. 결합 인덱스의 컬럼 순서에 따른 차이
인덱스정보인덱스정보
S_WORKPLAN : S_WORKPLAN_IDX : WORK_ORDER_DATEWORK_ORDER_DATE + DEPT_CODE +
GROUP_CODE
QUERYQUERY
해결방안해결방안 : 인덱스 칼럼 순서 : DEPT_CODE + GROUP_CODE + DEPT_CODE + GROUP_CODE +
WORK_ORDER_DATEWORK_ORDER_DATE
ROWS EXECUTION PLANROWS EXECUTION PLAN----- ---------------------------------------------------- 0 SELECT STATEMENT 2220 SORT (ORDER BY) 2220 TABLE ACCESS (BY ROWID) OF 'S_WORKPLAN'4602646026 INDEX (RANGE SCAN) OF 'S_WORKPLAN_IDX' (NON UNIQ)
DB 기술자문팀 10
SQLTuning
SQLTuning 사례 6. 결합 인덱스의 컬럼 순서에 따른 차이
WORK_ORDER_DATE + DEPT_CODE + GROUP_CODE LIKE '1'1%%'' = 1010 = 22
WORK_ORDER
11A 10 111A 10 2A 10 211A 20 311A 30 411B 10 2B 10 211B 20 211B 30 311B 40 411C 10 111C 10 2C 10 211C 20 32A 10 1
10 1 1A10 1 1C10 1 2A10 2 110 2 1A10 2 110 2 1B10 2 110 2 1C20 2 1B20 3 1A20 3 1C30 3 1B30 4 1A40 4 1B
DEPT_CODE + GROUP_CODE + WORK_ORDER_DATE = 1010 = 22 LIKE '1'1%%''
DEPT_CODE
GROUP_CODE
WORK_ORDER
DEPT_CODE
GROUP_CODE
DB 기술자문팀 11
SQLTuning
SQLTuning
SELECT SHIPPER, COUNT(*), SUM(AMT) FROM EX_SHIPPER WHERE SDATE BETWEENSDATE BETWEEN '950101' AND '950430' <- 4 <- 4 개월 분량개월 분량 , , 약 약 33 33 만 건만 건 AND SHIPPER INSHIPPER IN ('A', 'B', 'C') GROUP BY SHIPPER ORDER BY SUM(AMT) DESC ;
사례 7. 간단한 결합 인덱스지만 컬럼 순서 유의
인덱스정보인덱스정보
EX_SHIPPER : SHIP_DATE_IX : SDATESDATE + SHIPPEREX_SHIPPER 테이블의 분포도 : SDATE : 1 / 365 , SHIPPER : 1 / 10
QUERYQUERY
EXECUTION PLANEXECUTION PLAN----------------------------------------------SELECT STATEMENT COST ESTIMATE:N/A SORT ( GROUP BY ) TABLE ACCESS BY ROWID EX_SHIPPER ( 1 ) INDEX RANGE SCAN SHIP_DATE_IX ( NU )
DB 기술자문팀 12
SQLTuning
SQLTuning 사례 7. 간단한 결합 인덱스지만 컬럼 순서 유의
SHIP_DATE_IX
SDATE +SDATE +SHIPPERSHIPPER
EX_SHIPPER
●
●
●
●
22
차차
가가
공공
SHIP_DATE_IX
SHIPPER +SHIPPER +SDATESDATE
EX_SHIPPER
●
●
●
●
●
●
22
차차
가가
공공
DB 기술자문팀 13
SQLTuning
SQLTuning 사례 7. 간단한 결합 인덱스지만 컬럼 순서 유의
SHIPPER IN (SHIPPER IN (‘‘CC’’, , ‘‘BB’’, , ‘‘AA’’))
SHIP_DATE_IX1 : SHIPPER + SDATE + SHIP_DATE_IX1 : SHIPPER + SDATE +
AMTAMT
SHIP_DATE_IX
2 2
차차
가가
공공
SHIPPER + SDATE + AMTSHIPPER + SDATE + AMT
●●
●●
●●
EXECUTION PLANEXECUTION PLAN---------------------------------------------------SELECT STATEMENT SORT ( GROUP BY ) CONCATENATION INDEX RANGE SCAN : SHIP_DATE_IX1 ( NU ) INDEX RANGE SCAN : SHIP_DATE_IX1 ( NU ) INDEX RANGE SCAN : SHIP_DATE_IX1 ( NU )
처리범위는'SHIPPER =' 와'SDATE BETWEEN ...'에 의해서 결정
DB 기술자문팀 14
SQLTuning
SQLTuning
인덱스정보인덱스정보GFLT950 A : GFLT950_X1 : CAR_CODE + D_DAY + PART_CODEPART_CODE + TEAM_CODE (PK)GFLT950 A : GFLT950_X2 : TEAM_CODE + SPUM_CODEGFXC130 B : GFXC130_X1 : D_DAY + PART_CODE + TEAM_CODE (PK)
SELECT A.CAR_CODE, A.D_DAY, A.PART_CODE, A.SPUM_CODE,
A.ORDER_PRT, A.HP_Q, B.TEAM_CDOE, B.UPFR_DATE FROM GFLT950 A, GFXC130 B
WHERE A.PART_CODE = B.PART_CODEWHERE A.PART_CODE = B.PART_CODE AND A.ORDER_PRT = 100 AND B.D_DAY = :VALUE1 AND B.TEAM_CODE = :VALUE2 AND B.PART_CODE BETWEEN :VALUE3
AND :VALUE4;
사례 8. 조인시 사용된 결합 인덱스의 컬럼 순서
QUERYQUERY
ROWS EXECUTION PLANROWS EXECUTION PLAN----- -------------------------------------------------- 0 SELECT STATEMENT 184 NESTED LOOP1771817718 TABLE ACCESS (FULL) OF 'GFLT950' 184 TABLE ACCESS (BY ROWID) OF 'GFXC130' 184 INDEX (UNIQUE SCAN) OF 'GFXC130_X1' (UNIQUE)
AA BB
해결 방안 해결 방안 : : GFLT950 A : GFLT950_X1 : PART_CODEPART_CODE + CAR_CODE + D_DAY +
TEAM_CODE
DB 기술자문팀 15
SQLTuning
SQLTuning
GFLT950
# * PART_CODE# * CAR_CODE# * D_DAY# * TEAM_CODE SPUM_CODE ORDER_PRT F_HP_Q
사례 8. 조인시 사용된 결합 인덱스의 컬럼 순서
GFXC130
# * PART_CODE
# * D_DAY
# * TEAM_CODE
B_F_QTY
UPPER_DATE
UP
인덱스정보인덱스정보GFLT950 A : GFLT950_X1 : CAR_CODE + D_DAY + PART_CODEPART_CODE +
TEAM_CODE (PK)GFLT950 A : GFLT950_X2 : TEAM_CODE + SPUM_CODEGFXC130 B : GFXC130_X1 : D_DAY + PART_CODE + TEAM_CODE (PK)
DB 기술자문팀 16
SQLTuning
SQLTuning
SELECT A.CAR_CODE, A.D_DAY, A.PART_CODE, A.SPUM_CODE, A.ORDER.PRT, A.F_HP_Q, B.TEAM_CODE FROM GFLT920 A, GFXC130 B WHERE A.PART_CODE = A.PART_CODE = B.PART_CODE AND A.D_DAY = :VALUE1 AND B.PART_CODEB.PART_CODE BETWEENBETWEEN :VALUE3 AND :VALUE4 AND B.TEAM_CODE = :VALUE2;
사례 9. 결합 인덱스를 구성하는 컬럼 선택
인덱스정보인덱스정보 GFLT920 A : GFLT920_X1 : CAR_CODE + D_DAY + PART_CODE + TEAM_CODE
(PK) GFLT920 A : GFLT920_X2 : PART_CODEPART_CODE + SPUM_CODE GFXC130 B : GFXC130_X1 : PART_CODEPART_CODE + TEAM_CODE (PRIMARY KEY)
QUERYQUERY
ROWS EXECUTION PLANROWS EXECUTION PLAN---- ------------------------------------------------ 0 SELECT STATEMENT HINT : CHOOSE 23 NESTED LOOP 12 TABLE ACCESS (BY ROWID) OF 'GFXC130' 13 INDEX (RANGE SCAN) OF 'GFXC130_X1' (UNIQUE)6389 TABLE ACCESS (BY ROWID) OF 'GFLT920'63906390 INDEX (RANGE SCAN) OF 'GFLT920_X2'
BB
AA
DB 기술자문팀 17
SQLTuning
SQLTuning 사례 9. 결합 인덱스를 구성하는 컬럼 선택
12121313 63896389 23231212
GFXC130테이블 B
GFLT920테이블 A
GFXC130_X1 GFLT920_X2
해결방안해결방안
GFLT920 A : GFLT920_X2 : PART_CODE + D_DAYPART_CODE + D_DAY
63906390
●●●
●
●
●
●
●
●
X
O
O
X
●
●
●
DB 기술자문팀 18
SQLTuning
SQLTuning
SELECT A.PART_CODE, A.SPUM_CODE, A.D_DAY, A.B_F_QTY, A.TAG, B.ORDER_PRT, C.DC_CODE FROM GFBT400 A, GFXC440 BGFXC440 B, GFXC130 CGFXC130 C WHERE A.SPUM_CODE = B.SPUM_CODEB.SPUM_CODE AND A.PART_CODE = C.PART_CODEC.PART_CODE AND A.D_DAY = :B1A.D_DAY = :B1 AND A.TEAM_CODE = :B2AND A.TEAM_CODE = :B2;
사례 10. 결합 인덱스를 구성하는 컬럼 순서
인덱스정보인덱스정보GFBT400 A : GFBT400_X3 : TEAM_CODETEAM_CODE + SHOP_CODE + D_DAYD_DAY GFXC440 B : GFXC440_X1 : SPUM_CODESPUM_CODE (UNIQUE)GFXC130 C : GFXC130_X1 : PART_CODEPART_CODE (UNIQUE)
QUERYQUERY
ROWS EXECUTION PLANROWS EXECUTION PLAN----- --------------------------------------------------------- 0 SELECT STATEMENT 391 NESTED LOOPS 391 NESTED LOOPS 391391 TABLE ACCESS ( BY ROWID ) OF 'GFBT400'4827648276 INDEX ( RANGE SCAN ) OF 'GFBT400_X3' (NON-UNIQ) 391 TABLE ACCESS ( BY ROWID ) OF 'GFXC130' 391 INDEX ( UNIQUE SCAN ) OF 'GFXC130_X1' (UNIQ) 391 TABLE ACCESS ( BY ROWID ) OF 'GFXC440' 391 INDEX ( UNIQUE SCAN ) OF 'GFXC440_X1' (UNIQ)
AA
CC
BB
DB 기술자문팀 19
SQLTuning
SQLTuning 사례 10. 결합 인덱스를 구성하는 컬럼 순서
GFBT400_X3
TEAM_CODETEAM_CODE+ SHOP_CODE+ D_DAY
4827648276
GFBT400 AA
●
●
●
GFXC130_X1
391
GFXC130 CC
PART_CODE
GFXC440 BB
391
GFXC440_X1
SPUM_CODE
391 391391391
해결방안 해결방안 : : TEAM_CODE + D_DAYTEAM_CODE + D_DAY + SHOP_CODE+ SHOP_CODE
O
OX
X
X
OXX
X
DB 기술자문팀 20
SQLTuning
SQLTuning 사례 11. 조인하는 테이블의 순서에 따른 차이
수주진행현황 C# * 회사번호 # * 부서번호 # * 주문번호 # * 주문일자 # * 고객번호 직원번호
고객 D
# * 고객번호 고객이름 주소 주민등록번호 출고정지구분
주문 B
# * 주문번호 * 부서번호 * 고객번호 * 주문일자 * 직원번호 주문량
납품실행계획 A
# * 부서번호# * 주문번호 # * 직원번호 * 주문일자 납품예정일 소요비용 완료여부
DB 기술자문팀 21
SQLTuning
SQLTuning 사례 11. 조인하는 테이블의 순서에 따른 차이
인덱스정보인덱스정보납품실행계획 A : 납품실행 _PK : 주문번호주문번호 ++ 부서번호부서번호 + 직원번호주문 B : 주문 _PK : 주문번호 주문번호 수주진행현황 C : 수주진행현황 _PK : 회사번호 회사번호 + + 부서번호부서번호 + 주문번호 + 주문일자 + 고객번호 고객 D : 고객 _PK : 고객번호고객번호SELECT DISTINCTDISTINCT A.부서번호 , A.주문번호 , B.주문일자 , B.직원번호 , B.
고객번호 , D.출고중지구분 FROM 납품실행계획 납품실행계획 AA , 주문 주문 B ,B , 수주진행현황 수주진행현황 C C , 고객 고객 DD WHERE A.A. 부서번호부서번호 = B.부서번호 AND A.A. 주문번호주문번호 = B.주문번호 AND A.주문일자 = B.주문일자 AND C.부서번호 = B.부서번호 AND C.고객번호 = B.고객번호 AND C.직원번호 = B.직원번호 AND C.주문번호 = B.B. 주문번호주문번호 AND C.주문일자 = B.주문일자 AND C.고객번호 = D.D. 고객번호고객번호 AND C.C. 부서번호 부서번호 = 3000= 3000 AND C. C. 회사번호 회사번호 = 3 = 3 AND A.완료여부 IS NULL ;
ROWS EXECUTION PLANROWS EXECUTION PLAN---- ------------------------------------------------------------- 0 SELECT STATEMENT 7 SORT (UNIQUE)SORT (UNIQUE) 7 NESTED LOOPS1243 NESTED LOOPS1275 NESTED LOOPS1275 TABLE ACCESS (BY ROWID) OF '수주진행현황 '1276 INDEX (RANGE SCAN) OF ' 수주진행현황 _PK' (UNIQUE)1275 TABLE ACCESS (BY ROWID) OF '고객 '1275 INDEX (UNIQUE SCAN) OF ' 고객 _PK' (UNIQUE)1243 TABLE ACCESS (BY ROWID) OF '주문 '1275 INDEX (UNIQUE SCAN) OF ' 주문 _PK' (UNIQUE) 2020 TABLE ACCESS (BY ROWID) OF 'TABLE ACCESS (BY ROWID) OF '납품실행계획납품실행계획 ''12631263 INDEX (RANGE SCAN) OF ' 납품실행계획 _PK' (UNIQUE)
CC
DD
BB
AA
DB 기술자문팀 22
SQLTuning
SQLTuning 사례 11. 조인하는 테이블의 순서에 따른 차이
1276
1276
수주진행현황C
고객D
주문B
납품실행계획A
1275
1275
1275 1275 1243
1263
1263
20 77
X
O
O
●
●
●
1243
●
●
●
NoNoNoNo X
●
●
●
1275
1275
DB 기술자문팀 23
SQLTuning
SQLTuning 사례 11. 조인하는 테이블의 순서에 따른 차이
SELECT /*+ ORDERED *//*+ ORDERED */ DISTINCT A.부서번호 , A.주문번호 , B.주문일자, B.직원번호 , B.고객번호 , D.출고중지구분 FROM 수주진행현황 수주진행현황 CC , , 납품실행계획 납품실행계획 A A , 고객 고객 DD, 주문 주문 BB WHERE A.부서번호 = B.부서번호 AND A.주문번호 = B.주문번호 AND A.주문일자 = B.주문일자 AND C.AND C. 부서번호 부서번호 = = A.A. 부서번호부서번호 AND C.AND C. 주문번호 주문번호 = = A.A. 주문번호주문번호 AND C.AND C. 주문일자 주문일자 = = A.주문일자 AND C.주문번호 = B.B. 주문번호주문번호 AND C.주문일자 = B.주문일자 AND C.고객번호 = D.D. 고객번호고객번호 AND C.부서번호 = 3000 AND C.회사번호 = 3 AND A.완료여부 IS NULL ;
DB 기술자문팀 24
SQLTuning
SQLTuning 사례 11. 조인하는 테이블의 순서에 따른 차이
1276
수주진행현황 고객 주문납품실행계획
1275 12951295 2020 20 20 20 20 77
X
X
O
NoNo
●
●
●
●
●
●
●
●
●
20
DB 기술자문팀 25
SQLTuning
SQLTuning
SELECT INPTIDNO,INPTPKND,INPT,INPTLEVL,INPTMNDR,INPTDEPT,INPTCHRS,PBSCPNME, FLOOR(MONTH_BETWEEN(SYSDATE,TO_DATE(PBSCBIRT,'YYMMDD'))/12), PBSCRSEX,PBSCPHNI,CODEDESC
FROM THISCODE ATHISCODE A, THISPBSC BTHISPBSC B, THISINPT CTHISINPT C
WHERE C.INPTCHRS = SUBSTR( C.INPTCHRS = SUBSTR(A.CODENAMEA.CODENAME, 1, 1), 1, 1)
AND C.INPTDATE = :B1AND C.INPTDATE = :B1
AND C.INPTGUBN IN ('A', 'B')
AND C.INPTBYBY LIKE '1%'
AND C.INPTIDNO = B.PBSCIDNOB.PBSCIDNO
AND A.CODEGUBNA.CODEGUBN = '11';
사례 12. 인덱스 컬럼의 분리에 따른 문제 해결
인덱스정보인덱스정보THISCODE A : THISCODE_PK1 : CODEGUBNCODEGUBN +
CODENAMETHISPBSC B : THISPBSC_PK1 : PBSCIDNOPBSCIDNOTHISINPT C : THISINPT_IDX1 : INPTDATE + INPTDATE + INPTCHRSINPTCHRS
QUERYQUERY
ROWS EXECUTION PLANROWS EXECUTION PLAN----- -------------------------------------------------------
0 SELECT STATEMENT 40 NESTED LOOPS 40 NESTED LOOPS 480 TABLE ACCESS (BY ROWID) OF 'THISINPT' 481 INDEX (RANGE SCAN) OF 'THISINPT_IDX1'(NON-UNIQUE)
4040 TABLE ACCESS (BY ROWID) OF 'THISCODE'32903290 INDEX (RANGE SCAN) OF 'THISCODE_PK1'(UNIQUE)
40 TABLE ACCESS (BY ROWID) OF 'THISPBSC' 40 INDEX (UNIQUE SCAN) OF 'THISPBSC_PK1'(UNIQUE)
Access Access 비 효율의비 효율의발생 부분발생 부분
CC
AA
BB
DB 기술자문팀 26
SQLTuning
SQLTuning
THISINPT_IDX1
INPTDATEINPTDATE+ INPTCHRS+ INPTCHRS
481481
THISINPT CC THISCODE_PK1
480480
THISCODE AA
CODEGUBNCODEGUBN+ CODENAME
THISPBSC BB
4040
THISPBSC_PK1
PBSCIDNOPBSCIDNO
4040 4040
사례 12. 인덱스 컬럼의 분리에 따른 문제 해결
32903290480480 4040
●
●
●
X
X
XXX
X
O
O
O
4040
DB 기술자문팀 27
SQLTuning
SQLTuning 사례 12. 인덱스 컬럼의 분리에 따른 문제 해결
문제점문제점
모델링 잘못모델링 잘못 : : C.INPTCHRS = SUBSTR(A.CODENAME, 1, 1)C.INPTCHRS = SUBSTR(A.CODENAME, 1, 1)
조인순서조인순서 :: THISINPT(C) --> THISCODE(A) THISINPT(C) --> THISCODE(A)
해결방안해결방안THISCODE(A) --> THISINPT(C) --> THISPBSC(B)THISCODE(A) --> THISINPT(C) --> THISPBSC(B)
SELECT /*+ ORDERED *//*+ ORDERED */ INPTIDNO,INPTPKND,INPT, ..... ............ FROM THISCODE A, THISINPT C, THISPBSC BTHISCODE A, THISINPT C, THISPBSC B WHERE C.INPTCHRS = SUBSTR(C.INPTCHRS = SUBSTR(A.CODENAMEA.CODENAME, 1, 1), 1, 1) AND C.INPTDATE = :B1C.INPTDATE = :B1 AND C.INPTGUBN IN ('A','B') AND C.INPTBYBY
LIKE '1%' AND C.INPTIDNO = B.PBSCIDNOB.PBSCIDNO AND A.CODEGUBN = '11'A.CODEGUBN = '11' ;
DB 기술자문팀 28
SQLTuning
SQLTuning 사례 13. 조인을 활용한 GROUP BY 의 처리
인덱스정보인덱스정보
SALE : SALE_PROD_NO_SALEDATE : PROD_NO + SALEDATE (NON UNIQUE)PRODUCT : PK_PRODUCT : PROD_NO (PRIMARY PRIMARY
KEYKEY)
QUERYQUERYSELECT PROD_NO, SUM ( SALE_AMT * UNIT_PRICE) FROM SALE WHERE PROD_NO BETWEENBETWEEN 'P20150' AND 'P20200' 'P20150' AND 'P20200' AND SALEDATE LIKELIKE '1995%' GROUP BY PROD_NO ;
DB 기술자문팀 29
SQLTuning
SQLTuning 사례 13. 조인을 활용한 GROUP BY 의 처리
PROD_NO + SALEDATE
PROD_NO SALEDATE ● ● ● ●P20150P20150 19940110 ● ● ● ●P20150P20150 19950120 ● ● ● ●P20151P20151 19940102 ● ● ● ●P20151P20151 19951227 ● ● ● ●P20200P20200 19940120 ● ● ● ●P20200P20200 19951216 ● ● ● ●
처
리
범
위
SALE
PROD_NO + SALEDATE
PROD_NO SALEDATE ● ● ● ●P20150 19940110 ● ● ● ●P20150P20150 1995 19950120 ● ● ● ●P20151 19940102 ● ● ● ●P20151P20151 199519951227 ● ● ● ●P20190 19940120 ● ● ● ●P20200P20200 199519951216 ● ● ● ●
처
리
범
위
PROD_NO
P20148P20149P20150P20151 ● ● ● P20198P20199P20200 ● ● ●
PROD_NO
해
결
방
안
PRODUCT
SALE
DB 기술자문팀 30
SQLTuning
SQLTuning 사례 14. OR 사용 시 주의할 점
인덱스정보인덱스정보CHULGOT : CHULGOT_IX : CHULDATE + ITEMCHULGOT : CH_STATUS_ITEM : STATUS + ITEMCHULGOT : CH_CHULNO : CHULNO
QUERYQUERY
(CASE 1)(CASE 1)
SELECT SUM(CNT) FROM (SELECT COUNT(*) AS CNT FROM CHULGOT WHERE :SW = 1 AND CHULDATE = '941130'WHERE :SW = 1 AND CHULDATE = '941130' UNION ALLUNION ALL SELECT COUNT(*) AS CNT FROM CHULGOT WHERE :SW = 2 AND CHULDATE+0 LIKE '96%' WHERE :SW = 2 AND CHULDATE+0 LIKE '96%' );
SELECT COUNT(*) FROM CHULGOT WHERE (:SW = 1 AND CHULDATE = '941130')(:SW = 1 AND CHULDATE = '941130') OR OR (:SW = 2 AND CHULDATE+0 LIKE '96%') (:SW = 2 AND CHULDATE+0 LIKE '96%') ;
개선된개선된 QUERYQUERY
DB 기술자문팀 31
SQLTuning
SQLTuning 사례 14. OR 사용 시 주의할 점
SELECT COUNT(*) FROM CHULGOT WHERE CHULNO = '254'CHULNO = '254' OROR (:FILED1 + :FILED2 ) > 0 ; (:FILED1 + :FILED2 ) > 0 ;
SELECT MAXMAX(CNT) FROM ( SELECT COUNT(*) AS CNT FROM CHULGOT WHERE CHULNO = '254' CHULNO = '254' UNION ALLUNION ALL SELECT COUNT(*) AS CNT FROM CHULGOT WHERE (:FILED1 + :FILED2) > 0 (:FILED1 + :FILED2) > 0 ) ;
QUERY (CASE 2)QUERY (CASE 2)
개선된개선된 QUERYQUERY
DB 기술자문팀 32
SQLTuning
SQLTuning 사례 14. OR 사용 시 주의할 점
SELECT --+ RULE CHULNO, CUSTNO, CHULDATE,UNCOST FROM CHULGOT WHERE STATUS LIKE DECODE( :SW, 1, '2%') STATUS LIKE DECODE( :SW, 1, '2%') <--- <--- ②② OR STATUS LIKE DECODE( :SW, 1, '1%' , '3%') ;OR STATUS LIKE DECODE( :SW, 1, '1%' , '3%') ; <--- <--- ① ① 먼저 수행먼저 수행
SELECT --+ RULE CHULNO, CUSTNO, CHULDATE,UNCOST FROM CHULGOT WHERE (:SW = 1 AND (STATUS LIKE '1%') (:SW = 1 AND (STATUS LIKE '1%') OR (:SW = 1 AND (STATUS LIKE '2%')OR (:SW = 1 AND (STATUS LIKE '2%') OR (:SW = 2 AND (STATUS LIKE '3%')OR (:SW = 2 AND (STATUS LIKE '3%') ORDER BY STATUS ;
SELECT --+ RULE CHULNO, CUSTNO, CHULDATE,UNCOST FROM CHULGOT WHERE (:SW = 1 AND AND (STATUS LIKE '1%' OR OR STATUS LIKE ‘2%’) ) OROR (:SW = 2 AND (STATUS LIKE '3%') ) ORDER BY STATUS ;
QUERY (CASE 3)QUERY (CASE 3)
개선된개선된 QUERY QUERY
11
ORDER BY 절 없음 ! 개선된개선된 QUERY QUERY
22
DB 기술자문팀 33
SQLTuning
SQLTuning
SELECT --+ RULE CHULNO, CUSTNO, CHULDATE,UNCOST FROM CHULGOT WHERE ( :SW = 1 AND STATUS = 10 ) ( :SW = 1 AND STATUS = 10 )
OR OR ( :SW = 2 AND STATUS BETWEEN 20 AND 40 ) ( :SW = 2 AND STATUS BETWEEN 20 AND 40 ) ;
사례 14. OR 사용 시 주의할 점
SELECT --+ RULE
CHULNO, CUSTNO, CHULDATE,UNCOST
FROM CHULGOT
WHERE STATUS BETWEEN DECODE ( :SW , 1 , 10 , 2, 20 ) STATUS BETWEEN DECODE ( :SW , 1 , 10 , 2, 20 )
AND DECODE ( :SW , 1 , 10 , 2, 40 )AND DECODE ( :SW , 1 , 10 , 2, 40 ) ;
QUERY (CASE 4)QUERY (CASE 4)
개선된 개선된 QUERYQUERY
DB 기술자문팀 34
SQLTuning
SQLTuning 사례 15. OUTER 조인의 정확한 이해
A AAB 111
B AAC 123
C ABA 222
D ABB 233
E ABC 143
A 10 AA
B 10 AB
C 10 AC
O
O
O
O
O
O
O
O
X
X
TAB1 TAB2
A AAB 111 A 10 AA
B AAC 123 B 10 AB
C ABA 222 C 10 AC
D ABB 233D ABB 233
E ABC 143E ABC 143
원하는 결과원하는 결과
KEY FLD1 FLD2 KEY COL1 COL2
인덱스정보인덱스정보
TAB1 X : TAB1_IX : FLD1 + KEYTAB2 Y : TAB2_IX : COL1 + KEY
DB 기술자문팀 35
SQLTuning
SQLTuning 사례 15. OUTER 조인의 정확한 이해
QUERYQUERY
SELECT X.KEY, X.FLD1, X.FLD2, Y.KEY, Y.COL1, Y.COL2 FROM TAB1 X, TAB2 Y WHERE X.KEY = Y.KEY(+)X.KEY = Y.KEY(+) AND X.FLD1 > 'AAA' AND Y.COL1 = 10 Y.COL1 = 10 ;
SELECT X.KEY, X.FLD1, X.FLD2, Y.KEY, Y.COL1, Y.COL2 FROM TAB1 X, TAB2 Y WHERE X.KEY = Y.KEY(+)X.KEY = Y.KEY(+) AND X.FLD1 > 'AAA' AND (Y.COL1 = 10 OR Y.COL1 IS NULL) ; (Y.COL1 = 10 OR Y.COL1 IS NULL) ;
SELECT X.KEY, X.FLD1, X.FLD2, Y.KEY, Y.COL1, Y.COL2 FROM TAB1 X, TAB2 Y WHERE X.KEY = Y.KEY(+)X.KEY = Y.KEY(+) AND X.FLD1 > 'AAA' AND Y.COL1Y.COL1(+)(+) = 10 ; = 10 ;
원하는 결과 나오지 않음
COL1+KEY 순서이므로 인덱스 사용 불가 KEY+COL1 이면 인덱스 사용 가능
COL1+KEY 인덱스 사용 가능 KEY+COL1 이라도 사용 가능
TAB1 X : TAB1_IX : FLD1 + KEYTAB2 Y : TAB2_IX : COL1 + KEY
DB 기술자문팀 36
SQLTuning
SQLTuning 사례 16. 복잡한 로직을 OUTER 조인으로 해결
카드엠보싱내역 테이블 # * 카드번호 # * 일련번호 유형 접수일자 발행일자 영업점번호 담당자 ID
소개 소개 : : OUTER 조인과 DECODE 를 이용하여 복잡한 로직을 간단히 해결
요구 사항요구 사항 입력된 카드번호에 엠보싱이 요구될 경우 최초 엠보싱일 경우에는
일련번호를 1 로 셋팅하고 , 이미 엠보싱이 된 경우에는 입력된 카드번호의 일련번호 중 최대 번호 (MAX 일련번호 ) 를 찾아서 그 번호에 +1 을 하여 카드엠보싱내역에 INSERT 한다 .
DB 기술자문팀 37
SQLTuning
SQLTuning 사례 16. 복잡한 로직을 OUTER 조인으로 해결
EXEC SQL SELECT MAX( 일련번호 ) + 1 INTO : 다음일련번호 FROM 카드엠보싱내역 WHERE 카드번호 = : 입력카드번호 ;
IF (SQLCA.SQLCODE = = 1403) /* 카드번호 NOT FOUND */THEN EXEC SQL INSERT INTO 카드엠보싱내역 VALUES( : 입력카드번호 , 1, : 유형 , : 접수일자 , : 발행일자 , : 영업점번호 , : 담당자 ID ) ;ELSE EXEC SQL INSERT INTO 카드엠보싱내역 VALUES( : 입력카드번호 , : 다음일련번호 , : 유형 , :
접수일자 , : 발행일자 , : 영업점번호 , : 담당자 ID ) ;
일반적인 로직일반적인 로직
DB 기술자문팀 38
SQLTuning
SQLTuning 사례 16. 복잡한 로직을 OUTER 조인으로 해결
• 개선된 QUERY
OUTER JOIN 을 사용하여 한번에 INSERT 로 작업 수행
INSERT INTO 카드엠보싱내역 SELECT /*+ INDEX_DESC(B TBCARDEMBO_PK) USE_NL(A B) *//*+ INDEX_DESC(B TBCARDEMBO_PK) USE_NL(A B) */ : 입력카드번호 , DECODE(B. 카드번호 , NULL, 1, B. 일련번호 +1),
: 유형 , : 접수일자 , : 발행일자 , : 담당자 ID FROM 카드엠보싱내역 B, (SELECT :(SELECT : 입력카드번호 입력카드번호 AS AS 입력카드번호 입력카드번호 FROM DUAL) AFROM DUAL) A WHERE A.A. 입력카드번호 입력카드번호 = B.= B. 카드번호카드번호 (+)(+) AND ROWNUM = 1 ;AND ROWNUM = 1 ;
SORT MERGE 로 풀리는 것 방지
DB 기술자문팀 39
SQLTuning
SQLTuning 사례 17. DECODE 를 활용한 SQL 통합
QUERYQUERY
SELECT NVL(SUM(DACT_MH),0), NVL(SUM(DACT_MH),0), NVL(SUM(DACT_AMT),0)NVL(SUM(DACT_AMT),0)FROM S_DAY_ACTSCHWHERE ORDERNO = :B1 AND ITEMNO = :B2;
SELECT NVL(SUM(DACT_MH),0), NVL(SUM(DACT_MH),0), NVL(SUM(DACT_AMT),0)NVL(SUM(DACT_AMT),0)FROM S_DAY_ACTSCHWHERE ORDERNO = :B1 AND ITEMNO = :B2 AND CON_CODE IS NOT NULL;AND CON_CODE IS NOT NULL;
SELECT NVL(SUM(DACT_MH),0), NVL(SUM(DACT_MH),0), NVL(SUM(DACT_AMT),0)NVL(SUM(DACT_AMT),0)FROM S_DAY_ACTSCHWHERE ORDERNO = :B1 AND ITEMNO = :B2; AND (CON_CODE IS NULL OR AND (CON_CODE IS NULL OR LENGTH(CON_CODE) = 1 );LENGTH(CON_CODE) = 1 );
DB 기술자문팀 40
SQLTuning
SQLTuning 사례 17. DECODE 를 활용한 SQL 통합
SELECT NVL(SUM(DACT_MH ),0), NVL(SUM(DACT_AMT),0), NVL(SUM(DECODE( CON_CODE, NULL, 0, DACT_MH ))SUM(DECODE( CON_CODE, NULL, 0, DACT_MH )),0), NVL(SUM(DECODE( CON_CODE, NULL, 0, DACT_AMT))SUM(DECODE( CON_CODE, NULL, 0, DACT_AMT)),0), NVL(SUM(DECODESUM(DECODE( ( CON_CODE, NULL, DACT_MH,CON_CODE, NULL, DACT_MH, DECODE(LENGTH(CON_CODE), 1, DACT_MH, 0) DECODE(LENGTH(CON_CODE), 1, DACT_MH, 0) )))), 0), NVL(SUM(DECODESUM(DECODE( ( CON_CODE, NULL, DACT_AMTCON_CODE, NULL, DACT_AMT, DECODE(LENGTH(CON_CODE), 1, DACT_AMT,0) DECODE(LENGTH(CON_CODE), 1, DACT_AMT,0) )))), 0),FROM S_DAY_ACTSCHWHERE ORDERNO = :B1 AND ITEMNO = :B2;
개선된 개선된 QUERYQUERY
DB 기술자문팀 41
SQLTuning
SQLTuning 사례 18. 과도한 DECODE 의 사용
QUERYQUERY
SELECT B.TM, M.TAX, M.PUMMOK, SUM(DECODE(NAPBAN, '1', P.SSU, 0)), SUM(DECODE(NAPBAN, '1', P.KUMEK1, 0)), SUM(DECODE(NAPBAN, '1', DECODE(B.BOKWAN, '1', P.KUMEK2, 0))), SUM(DECODE(NAPBAN, '1', DECODE(B.BOKWAN, '1', P.KUMEK2, 0))), SUM(DECODE(NAPBAN, '1', DECODE(B.BOKWAN, '2', P.KUMEK2, 0))), SUM(DECODE(NAPBAN, '1', DECODE(B.BOKWAN, '2', P.KUMEK2, 0))), SUM(DECODE(NAPBAN, '1', DECODE(B.BOKWAN, '3', P.KUMEK2, 0))), SUM(DECODE(NAPBAN, '1', DECODE(B.BOKWAN, '3', P.KUMEK2, 0))), SUM(DECODE(NAPBAN, '2', P.SSU, 0)), SUM(DECODE(NAPBAN, '2', P.KUMEK1, 0)), SUM(DECODE(NAPBAN, '2', DECODE(B.BOKWAN, '1', P.KUMEK2, 0))), SUM(DECODE(NAPBAN, '2', DECODE(B.BOKWAN, '2', P.KUMEK2, 0))), SUM(DECODE(NAPBAN, '2', DECODE(B.BOKWAN, '3', P.KUMEK2, 0))), SUM(DECODE(NAPBAN, '3', P.SSU, 0)), SUM(DECODE(NAPBAN, '3', P.KUMEK1, 0)), SUM(DECODE(NAPBAN, '3', DECODE(B.BOKWAN, '1', P.KUMEK2, 0))), SUM(DECODE(NAPBAN, '3', DECODE(B.BOKWAN, '2', P.KUMEK2, 0))), SUM(DECODE(NAPBAN, '3', DECODE(B.BOKWAN, '3', P.KUMEK2, 0))), FROM GGB M, GPM P, MJ B WHERE B.YT = P.YT AND B.MAEJANG = P.MAEJANG AND M.CODE = P.PUMMOK AND P.DATE BETWEEN :B1 AND :B2 GROUP BY B.TM, M.TAX, M.PUMMOKGROUP BY B.TM, M.TAX, M.PUMMOK ORDER BY B.TM, M.TAX, M.PUMMOK ;ORDER BY B.TM, M.TAX, M.PUMMOK ;
DB 기술자문팀 42
SQLTuning
SQLTuning 사례 18. 과도한 DECODE 의 사용
SELECT B.TM, M.TAX, M.PUMMOK, SUM(DECODE(NAPBAN, '1', P.SSU, 0)), SUM(DECODE(NAPBAN, '1', P.KUMEK1, 0)), SUM(DECODE(NAPBAN||B.BOKWAN, '11', P.KUMEK2, 0)), SUM(DECODE(NAPBAN||B.BOKWAN, '11', P.KUMEK2, 0)), SUM(DECODE(NAPBAN||B.BOKWAN, '12', P.KUMEK2, 0)), SUM(DECODE(NAPBAN||B.BOKWAN, '12', P.KUMEK2, 0)), SUM(DECODE(NAPBAN||B.BOKWAN, '13', P.KUMEK2, 0)),SUM(DECODE(NAPBAN||B.BOKWAN, '13', P.KUMEK2, 0)), SUM(DECODE(NAPBAN, '2', P.SSU, 0)), SUM(DECODE(NAPBAN, '2', P.KUMEK1, 0)), SUM(DECODE(NAPBAN||B.BOKWAN, '21', P.KUMEK2, 0)), SUM(DECODE(NAPBAN||B.BOKWAN, '22', P.KUMEK2, 0)), SUM(DECODE(NAPBAN||B.BOKWAN, '23', P.KUMEK2, 0)), SUM(DECODE(NAPBAN, '3', P.SSU, 0)), SUM(DECODE(NAPBAN, '3', P.KUMEK1, 0)), SUM(DECODE(NAPBAN||B.BOKWAN, '31', P.KUMEK2, 0)), SUM(DECODE(NAPBAN||B.BOKWAN, '32', P.KUMEK2, 0)), SUM(DECODE(NAPBAN||B.BOKWAN, '33', P.KUMEK2, 0)), FROM GGB M, GPM P, MJ B WHERE B.YT = P.YT AND B.MAEJANG = P.MAEJANG AND M.CODE = P.PUMMOK AND P.DATE BETWEEN :B1 AND :B2 GROUP BY B.TM, M.TAX, M.PUMMOKGROUP BY B.TM, M.TAX, M.PUMMOK ;
개선된 개선된 QUERYQUERY
DB 기술자문팀 43
SQLTuning
SQLTuning 사례 19. 비숫한 SQL 을 통합하여 SUM(DECODE) 로
소개 소개 : : WHERE 조건이 조금 다르면서 동일한 테이블을 사용하는 SQL 통합
유사한 유사한 SQLSQL
EXEC SQL SELECT MAX(LINE_NO) INTO :TOT_LINE_NO FROM BA004DM WHERE BRK_CD= :BRK_CD AND DCL_YEAR = :DCL_YEAR AND SBM_SRL_NO = :SBM_SRL_NO AND DITC = :DITC ;
EXEC SQL SELECT COUNT(LINE_NO) INTO :M_LINE_NO FROM BA004DM WHERE BRK_CD = :BRK_CD AND DCL_YEAR = :DCL_YEAR AND SBM_SRL_NO = :SBM_SRL_NO AND DITC = :DITC AND LINE_NO < 0AND LINE_NO < 0 ;
DB 기술자문팀 44
SQLTuning
SQLTuning 사례 19. 비숫한 SQL 을 통합하여 SUM(DECOD
E) 로
EXEC SQL SELECT MAX (LINE_NO) , SUM(DECODE(SIGN(LINE_NO), -1, 1 )) INTO :TOT_LINE_NO, :M_LINE_NO FROM BA004DM WHERE BRK_CD= :BRK_CD AND DCL_YEAR = :DCL_YEAR AND SBM_SRL_NO = :SBM_SRL_NO AND DITC = :DITC ;
해결 방안해결 방안
DB 기술자문팀 45
SQLTuning
SQLTuning 사례 20. DECODE 와 GROUP BY 의 효율적인
사용
자격등록마스터 테이블 (약 100 만 건) 요구 사항
등록자 ID QUAL_ID NUMBER PRIMARY KEY
등록자명 QUAL_NM VARCHAR2(10)
직종코드 JOB_CLSS CHAR(2)
성별 SEX CHAR(1)
등록일자 REG_DATE CHAR(8)
급여 SALARY NUMBER
가족수 FAMILY_CNT NUMBER
등급 GRAD_CLSS CHAR(1)
1996 년도 자료 중 직종별,성별로 구분하여 등록 월별로등록된 건수를 표시하라.
[힌트]
GROUP BY 직종별, 성별이 되어야 하고 세로로 된 데이터를 가로로 펼치기 위해DECODE를 사용한다.
DB 기술자문팀 46
SQLTuning
SQLTuning
SELECT JOB_CLSS, SEX, SUM(DECODE(SUBSTR(REG_DATE,1,6),’199601’,1,0)) AS 9601 월 , SUM(DECODE(SUBSTR(REG_DATE,1,6),’199602’,1,0)) AS 9602 월 ,
............ SUM(DECODE(SUBSTR(REG_DATE,1,6),’199612’,1,0)) AS 9612 월 FROM QUALIFIER GROUP BY JOB_CLSS, SEX;
사례 20. DECODE 와 GROUP BY 의 효율적인 사용
2 분 24 초
병렬 처리병렬 처리
SELECT /*+ FULL(QUALIFIER) PARALLEL(QUALIFIER 2) *//*+ FULL(QUALIFIER) PARALLEL(QUALIFIER 2) */ JOB_CLSS, SEX, SUM(DECODE(SUBSTR(REG_DATE,1,6),’199601’,1,0)) AS 9601 월 ,
............ FROM QUALIFIER GROUP BY JOB_CLSS, SEX ORDER BY 1, 2ORDER BY 1, 2; 1 분 13 초
DB 기술자문팀 47
SQLTuning
SQLTuning
SELECT JC, SEX, SUM(DECODE(REG_MM,'199601',CNT,0)) AS 9601 월 , SUM(DECODE(REG_MM,'199602',CNT,0)) AS 9602 월 , SUM(DECODE(REG_MM,'199603',CNT,0)) AS 9603 월 , SUM(DECODE(REG_MM,'199604',CNT,0)) AS 9604 월 , ........ SUM(DECODE(REG_MM,'199610',CNT,0)) AS 9610 월 , SUM(DECODE(REG_MM,'199611',CNT,0)) AS 9611 월 , SUM(DECODE(REG_MM,'199612',CNT,0)) AS 9612 월FROM (SELECT /*+ FULL(QUALIFIER) PARALLEL(QUALIFIER,2) *//*+ FULL(QUALIFIER) PARALLEL(QUALIFIER,2) */ JOB_CLSS AS JC, SEX, SUBSTR(REG_DATE,1,6) AS REG_MM, COUNT(*) AS CNT FROM QUALIFIER GROUP BY JOB_CLSS, SEX, SUBSTR(REG_DATE,1,6)GROUP BY JOB_CLSS, SEX, SUBSTR(REG_DATE,1,6) )GROUP BY JC, SEX ;
사례 20. DECODE 와 GROUP BY 의 효율적인 사용
Parallel: 14 14 초초
No Parallel : 27No Parallel : 27 초초
DB 기술자문팀 48
SQLTuning
SQLTuning
소개 소개 : : 데이터 복제를 이용하여 기준이 되는 항목에 대하여 데이터가 없어도 빠짐없이 모두 표시
사례 21. 데이터 복제를 이용하여 빠짐없이 표시
위와 같은 환경하에 모든 지역에 대하여 한주일 동안 자격을 취득한 모든 사람을 지역별 , 성별로 구분하여 표시
원하는 기간에 대해 해당지역에 자격취득자가 없는 경우에도 남녀 항목이 생성되어 “ 0” 이라는 값을 가짐
피보험자격정보
# * 주민등록번호 성명 자격취득일자 지역코드 (FK) 주소 성별
지역정보
# * 지역코드 지역명 대표지부장
DB 기술자문팀 49
SQLTuning
SQLTuning 사례 21. 데이터 복제를 이용하여 빠짐없이 표시
표시 예표시 예
지역명 성 별 기준일 +1 +2 +3 +4 +5 +6
서울
서울
.....
경남
경남
제주
제주
남
여
.....
남
여
남
여
1
2
.....
1
0
0
0
0
1
.....
1
0
0
0
3
.....
1
0
0
1
3
4
.....
2
0
0
0
2
1
.....
1
0
0
0
1
0
.....
0
0
0
0
0
1
.....
0
0
0
0
DB 기술자문팀 50
SQLTuning
SQLTuning 사례 21. 데이터 복제를 이용하여 빠짐없이 표시
간단한 간단한 SQLSQL
SELECT 지역명 , 성별 , SUM(DECODE( 자격취득일자 , : 입력일자 , 1), SUM(DECODE( 자격취득일자 , : 입력일자 +1, 1), SUM(DECODE( 자격취득일자 , : 입력일자 +2, 1), SUM(DECODE( 자격취득일자 , : 입력일자 +3, 1), SUM(DECODE( 자격취득일자 , : 입력일자 +4, 1), SUM(DECODE( 자격취득일자 , : 입력일자 +5, 1), SUM(DECODE( 자격취득일자 , : 입력일자 +6, 1), FROM 피보험자자격정보 A, 지역정보 B WHERE A. 자격취득일자 BETWEEN : 입력일자 AND : 입력일자 +6 AND A. 지역코드 = B. 지역코드 GROUP BY B. 지역명 , A. 성별 ;
문제점 문제점 : : “ 경남지역 여”나 “제주지역 남”처럼 자격을 취득한 로우가 없으면 해당로우가 나타나지 않음
DB 기술자문팀 51
SQLTuning
SQLTuning 사례 21. 데이터 복제를 이용하여 빠짐없이 표시
해결 방안 해결 방안
서울 남 1 0 5 3 2 1 0
서울 여 2 1 3 4 1 0 1
경남 남 1 0 1 2 1 0 0
제주 여 0 0 1 0 0 0 0
GROUP BY 지역명 , 성별
+
남 여
서울 남 ..... 남서울 남 ..... 여서울 여 ..... 남서울 여 ..... 여경남 남 ..... 남경남 남 ..... 여제주 여 ..... 남제주 여 ..... 여
서울 남 ..... : 남서울 남 0....0 : 여서울 여 0....0 : 남서울 여 ..... : 여경남 남 ..... : 남경남 남 0....0 : 여제주 여 0....0 : 남제주 여 ..... : 여
Join
Deco
de
Gro
up
By
DB 기술자문팀 52
SQLTuning
SQLTuning 사례 21. 데이터 복제를 이용하여 빠짐없이 표시
SQLSQLSELECT V. 지역명 ,R. 성별 , SUM (DECODE(V.SUM (DECODE(V. 성별성별 ,R.,R. 성별성별 ,SUM1,0) AS ,SUM1,0) AS 기준일 기준일 ,, SUM (DECODE(V.SUM (DECODE(V. 성별성별 ,R.,R. 성별성별 ,SUM1,0) AS ,SUM1,0) AS 기준일기준일 +1,+1, SUM (DECODE(V.SUM (DECODE(V. 성별성별 ,R.,R. 성별성별 ,SUM1,0) AS ,SUM1,0) AS 기준일기준일 +2,+2, SUM (DECODE(V.SUM (DECODE(V. 성별성별 ,R.,R. 성별성별 ,SUM1,0) AS ,SUM1,0) AS 기준일기준일 +3,+3, SUM (DECODE(V.SUM (DECODE(V. 성별성별 ,R.,R. 성별성별 ,SUM1,0) AS ,SUM1,0) AS 기준일기준일 +4,+4, SUM (DECODE(V.SUM (DECODE(V. 성별성별 ,R.,R. 성별성별 ,SUM1,0) AS ,SUM1,0) AS 기준일기준일 +5,+5, SUM (DECODE(V.SUM (DECODE(V. 성별성별 ,R.,R. 성별성별 ,SUM1,0) AS ,SUM1,0) AS 기준일기준일 +6,+6,FROM (SELECT B. 지역명 , A. 성별 , SUM (DECODE(SUM (DECODE( 자격취득일자자격취득일자 , :, : 입력일자 입력일자 , 1) AS SUM1,, 1) AS SUM1, SUM (DECODE(SUM (DECODE( 자격취득일자자격취득일자 , :, : 입력일자입력일자 +1, 1) AS SUM2,+1, 1) AS SUM2, SUM (DECODE(SUM (DECODE( 자격취득일자자격취득일자 , :, : 입력일자입력일자 +2, 1) AS SUM3,+2, 1) AS SUM3, SUM (DECODE(SUM (DECODE( 자격취득일자자격취득일자 , :, : 입력일자입력일자 +3, 1) AS SUM4,+3, 1) AS SUM4, SUM (DECODE(SUM (DECODE( 자격취득일자자격취득일자 , :, : 입력일자입력일자 +4, 1) AS SUM5,+4, 1) AS SUM5, SUM (DECODE(SUM (DECODE( 자격취득일자자격취득일자 , :, : 입력일자입력일자 +5, 1) AS SUM6,+5, 1) AS SUM6, SUM (DECODE(SUM (DECODE( 자격취득일자자격취득일자 , :, : 입력일자입력일자 +6, 1) AS SUM7+6, 1) AS SUM7 FROM 피보험자자격정보 A, 지역정보 B WHERE A. 자격취득일자 BETWEEN : 입력일자 AND : 입력일자 + 6 AND A. 지역코드 = B. 지역코드 GROUP BY B.GROUP BY B. 지역명 지역명 , A., A. 성별성별 ) V, (SELECT '(SELECT ' 남남 ' AS ' AS 성별 성별 FROM DUALFROM DUAL UNION ALLUNION ALL SELECT 'SELECT ' 여여 ' AS ' AS 성별 성별 FROM DUAL) RFROM DUAL) RGROUP BY V.GROUP BY V. 지역명지역명 , R., R. 성별성별 ;
DB 기술자문팀 53
SQLTuning
SQLTuning 사례 21. 데이터 복제를 이용하여 빠짐없이 표시
서울 남 1 0 5 3 2 1 0
남
서울 남 1 0 5 3 2 1 0
여
서울 여 2 1 3 4 1 0 1
남
서울 여 2 1 3 4 1 0 1
여
경남 남 1 0 1 2 1 0 0
남
경남 남 1 0 1 2 1 0 0
여
제주 여 0 0 1 0 0 0 0
남
제주 여 0 0 1 0 0 0 0
여
DDEECCOODDEE
서울 남 1 0 5 3 2 1 0 남
서울 남 0 0 0 0 0 0 0 여
서울 여 0 0 0 0 0 0 0 남
서울 여 2 1 3 4 1 0 1 여
경남 남 1 0 1 2 1 0 0 남
경남 남 0 0 0 0 0 0 0 여
제주 여 0 0 0 0 0 0 0 남
제주 여 0 0 1 0 0 0 0 여
V. 지역명 R. 성별V.SUM1
GROUP BYGROUP BY
GROUP BYGROUP BY
GROUP BYGROUP BY
GROUP BYGROUP BY
DB 기술자문팀 54
SQLTuning
SQLTuning 사례 21. 데이터 복제를 이용하여 빠짐없이 표시
SQLSQL
SELECT V. 지역명 , R. 성별 , SUM (DECODE(V. 성별 ,R. 성별 ,SUM1,0) AS 기준일 , SUM (DECODE(V. 성별 ,R. 성별 ,SUM1,0) AS 기준일 +1, SUM (DECODE(V. 성별 ,R. 성별 ,SUM1,0) AS 기준일 +2, SUM (DECODE(V. 성별 ,R. 성별 ,SUM1,0) AS 기준일 +3, SUM (DECODE(V. 성별 ,R. 성별 ,SUM1,0) AS 기준일 +4, SUM (DECODE(V. 성별 ,R. 성별 ,SUM1,0) AS 기준일 +5, SUM (DECODE(V. 성별 ,R. 성별 ,SUM1,0) AS 기준일 +6,FROM (SELECT B. 지역명 , A. 성별 , SUM (DECODE( 자격취득일자 , : 입력일자 , 1) AS S
UM1, SUM (DECODE( 자격취득일자 , : 입력일자 +1, 1) AS SUM
2, SUM (DECODE( 자격취득일자 , : 입력일자 +2, 1) AS SUM
3, SUM (DECODE( 자격취득일자 , : 입력일자 +3, 1) AS SUM
4, SUM (DECODE( 자격취득일자 , : 입력일자 +4, 1) AS SUM
5, SUM (DECODE( 자격취득일자 , : 입력일자 +5, 1) AS SUM
6, SUM (DECODE( 자격취득일자 , : 입력일자 +6, 1) AS SUM
7 FROM (SELECT 자격취득일자 , 성별 , 지역코드 FROM 피보험자자격정보피보험자자격정보 WHERE 자격취득일자 자격취득일자 BETWEEN :BETWEEN : 입력일자 입력일자 AND :AND : 입력일자입력일자 +6 ) A,+6 ) A, 지역정보 B WHERE B.WHERE B. 지역코드 지역코드 = A.= A. 지역코드지역코드 (+) (+) GROUP BY B. 지역명 , A. 성별 ) V, (SELECT ' 남 ' AS 성별 FROM DUAL UNION ALL SELECT ' 여 ' AS 성별 FROM DUAL) RGROUP BY V. 지역명 , R. 성별 ;
DB 기술자문팀 55
SQLTuning
SQLTuning