SELECT * FROM TAB1
WHERE COL1 ='A'
AND COL2 BETWEEN '111' AND '112'
Rows Row Source Operation
------- ---------------------------------------------------
0 STATEMENT
0 INDEX RANGE SCAN OF XAK_TAB1 (NONUNIQUE)
SELECT * FROM TAB1
WHERE COL1 ='A'
AND COL2 IN ( '112','111')
Rows Row Source Operation
------- ---------------------------------------------------
0 STATEMENT
0 CONCATENATION
0 INDEX RANGE SCAN OF XAK_TAB1 (NONUNIQUE)
0 INDEX RANGE SCAN OF XAK_TAB1 (NONUNIQUE)
SELECT * FROM TAB1
WHERE 상품 ='PRINTER'
AND 매출일자 BETWEEN '19980302' AND '19980303'
SELECT * FROM TAB1
WHERE 상품='PRINTER'
AND 부서코드 LIKE '%'
AND 매출일자 BETWEEN '19980302' AND '19980303'
SELECT *
FROM TAB1
WHERE 상품 = 'PRINTER'
AND 부서코드 IN ( SELECT 부서코드 FROM 부서
WHERE 부서구문 = '영업' )
AND 매출일자 BETWEEN '19980302' AND '19980303';
EXECUTION PLAN
-----------------------------------------------------
0 SELECT STATEMENT
1 0 NESTED LOOPS
2 1 TABLE ACCESS (BY ROWID) OF '부서'
3 2 INDEX (RANGE SCAN) OF '부서' ( NON UNIQUE )
4 1 TABLE ACCESS (BY ROWID) OF 'TAB1'
5 4 INDEX (RANGE SCAN) OF 'TAB1' ( NON UNIQUE )
EXECUTION PLAN
-----------------------------------------------------
0 SELECT STATEMENT
1 0 NESTED LOOPS
2 1 VIEW
3 2 SORT(UNIQUE)
4 3 TABLE ACCESS (BY ROWID) OF '부서'
5 4 INDEX (RANGE SCAN) OF '부서' ( NON UNIQUE )
4 1 TABLE ACCESS (BY ROWID) OF 'TAB1'
5 4 INDEX (RANGE SCAN) OF 'TAB1' ( NON UNIQUE )
SELECT *
FROM TAB1
WHERE 상품 ='PRINTER'
AND 처리구분 BETWEEN '2' AND '3'
AND 판매일자 LIKE '199804%';
SELECT *
FROM TAB1
WHERE 상품 ='PRINTER'
AND 처리구분 IN ('2', '3' )
AND 판매일자 LIKE '199804%';
SELECT *
FROM TAB1
WHERE 상품 ='PRINTER'
AND 처리구분 IN ('1','2','3','4')
AND 판매일자 LIKE '199804%';
SELECT *
FROM TAB1
WHERE 상품 ='PRINTER'
AND 처리구분 IN ('4','3','2','1')
AND 판매일자 LIKE '199804%';
ONE 칼럼 인덱스 | 결합인덱스 |
---|---|
| 절대 NULL 값을 허용하지 말고 반드시 '상수값'을 부여하라는 것이다. |
SELECT *
FROM TAB1
WHERE 상품 ='PRINTER'
AND 처리구분 BETWEEN :VAL1 AND :VAL2
AND 판매일자 LIKE '199804%';
SELECT *
FROM TAB1
WHERE 상품 ='PRINTER'
AND 처리구분 IN ( :VAL1, :VAL2, :VAL3, :VAL4 )
AND 판매일자 LIKE '199804%';
제공자 역할 |
---|
\- 서브쿼리가 제공자 역할을 하기 위해서는 서브쿼리 내에 메인쿼리의 칼럼을 갖지 않아야 하며 서브쿼리가 제공한 값을 받은 메인쿼리의 컬럼이 반드시 처리주관 조건이 되어야 한다. |
SELECT *
FROM TAB1
WHERE 상품 ='PRINTER'
AND 부서 LIKE '210%'
AND 판매일자 BETWEEN '19980401' AND '19980415'
SELECT *
FROM TAB1
WHERE 상품 ='PRINTER'
AND 부서 IN ( SELECT 부서 FROM 부서테이블 WHERE 부서 LIKE '210%')
AND 판매일자 BETWEEN '19980401' AND '19980415'
CREATE TABLE YMD_DUAL
( YMD VARCHAR2(8), YMD_DATE DATE );
SELECT * FROM YMD_DUAL ;
DELETE YMD_DUAL ;
INSERT INTO YMD_DUAL SELECT TO_CHAR(TO_DATE('19591231','YYYYMMDD')+ROWNUM,'YYYYMMDD'), TO_DATE('19591231','YYYYMMDD')+ROWNUM
FROM CHECK_REBUILD
WHERE ROWNUM< =365000 ;
여기서 FROM절의 테이블은 ROW수가 365000 이 넘는 테이블이면 어떤것이라도 좋다
CREATE UNIQUE INDEX YMD_DUAL_PK1 ON YMD_DUAL ( YMD ) PCTFREE 0 ;
CREATE UNIQUE INDEX YMD_DUAL_PK2 ON YMD_DUAL ( YMD_DATE ) PCTFREE 0 ;
CREATE TABLE YM_DUAL (YM6, YM4)
AS SELECT DISTINCT SUBSTR(YMD,1,6),SUBSTR(YMD,3,4)
FROM YMD_DUAL ;
CREATE UNIQUE INDEX YM_DUAL_PK1 ON YM_DUAL ( YM6 ) PCTFREE 0 ;
CREATE INDEX YM_DUAL_PK2 ON YM_DUAL ( YM4 ) PCTFREE 0 ;
SELECT * FROM TAB1
WHERE 상품 ='PRINTER'
AND 판매일자 IN ( SELECT YMD FROM YMD_DUAL WHERE YMD '19980401' AND '19980415' )
AND 부서 LIKE '210%'
SELECT *
FROM TAB3
WHERE 자재 ='KH010'
AND 구매일자 BETWEEN :DATE1 AND :DATE2
SELECT *
FROM TAB3
WHERE 자재 ='KH010'
AND 용도구분 IN ( SELECT CEIL(ROWNUM/4)||'0'||MOD(ROWNUM,4)+4 FROM TABL3 WHERE ROWNUM <= 32 )
AND 구매일자 BETWEEN :DATE1 AND :DATE2
CREATE TABLE COPY_T ( NO, NO2 ) AS
SELECT ROWNUM, SUBSTR(TO_CHAR(ROWNUM,'09',2,2)
FROM CHECK_REBUILD
WHERE ROWNUM < = 31 ;
SELECT *
FROM TAB3
WHERE 자재 ='KH010'
AND 용도구분 IN ( SELECT TO_NUMBER(X.NO2)||(Y.NO2
FROM COPY_T X, COPY_T Y
WHERE X.NO2 < '08'
AND Y.NO2 <= DECODE(X.NO2,'03','03','07','03','04')
AND 구매일자 BETWEEN :DATE1 AND DATE2
SELECT EMPNO,ENAME,SAL
FROM EMP
WHERE EMPNO IN (7876,7900,75667,7900)
SELECT EMPNO,ENAME,SAL
FROM EMP
WHERE EMPNO IN (7900,7876,7900,7566)
SELECT 부서코드, SUM(매출액)
FROM TAB4
WHERE 사업장 = '서울'
AND 매출구분 IN ( :B1, :B2, :B3, :B4, :B5 )
AND 매출일자 LIKE :C1||'%'
GROUP BY 부서코드
ROWS EXECUTION PLAN
-------------------------------------------------------------------
0 SELECT STATEMENT
12 SORT ( GROUP BY )
0 CONCATENATION
0 TABLE ACCESS (BY ROWID) OF 'TAB4'
0 INDEX (RANGE SCAN) OF 'T_IDX' ( NON-UNIQUE) -> B5 = ''
0 TABLE ACCESS (BY ROWID) OF 'TAB4'
0 INDEX (RANGE SCAN) OF 'T_IDX' ( NON-UNIQUE) -> B4 = ''
73764 TABLE ACCESS (BY ROWID) OF 'TAB4'
73765 INDEX (RANGE SCAN) OF 'T_IDX' ( NON-UNIQUE) -> B3 = 'A'
34475 TABLE ACCESS (BY ROWID) OF 'TAB4'
34475 INDEX (RANGE SCAN) OF 'T_IDX' ( NON-UNIQUE) -> B2 = 'B'
0 TABLE ACCESS (BY ROWID) OF 'TAB4'
73765 INDEX (RANGE SCAN) OF 'T_IDX' ( NON-UNIQUE) -> B1 = 'A'
SELECT * FROM TAB1
WHERE 제품 = 'KH1101'
AND 부서코드 ='2110'
AND 매출구분 IN ('1','5','7' )
SELECT * FROM TAB1
WHERE 제품 = 'KH1101'
AND 부서코드 ='2110'
AND 매출구분 IN ('1','5','7' )
AND 매출일자 LIKE '199805%'
SELECT *
FROM TAB10
WHERE JE ='KH1101'
AND BU ='2110'
AND MAE1 IN ('1','5','7')
AND MAE2 IN ('19980501','19980506')
Rows Row Source Operation
------- ---------------------------------------------------
0 STATEMENT
3 TABLE ACCESS BY INDEX ROWID TAB10
4 INDEX RANGE SCAN OF XAK_TAB10 (NONUNIQUE)
SELECT /*+ USE_CONCAT */ *
FROM TAB10
WHERE JE ='KH1101'
AND BU ='2110'
AND MAE1 IN ('1','5','7')
AND MAE2 IN ('19980501','19980506')
Rows Row Source Operation
------- ---------------------------------------------------
0 STATEMENT
3 CONCATENATION
0 TABLE ACCESS BY INDEX ROWID TAB10
1 INDEX RANGE SCAN OF XAK_TAB10 (NONUNIQUE)
1 TABLE ACCESS BY INDEX ROWID TAB10
2 INDEX RANGE SCAN OF XAK_TAB10 (NONUNIQUE)
0 TABLE ACCESS BY INDEX ROWID TAB10
1 INDEX RANGE SCAN OF XAK_TAB10 (NONUNIQUE)
1 TABLE ACCESS BY INDEX ROWID TAB10
2 INDEX RANGE SCAN OF XAK_TAB10 (NONUNIQUE)
0 TABLE ACCESS BY INDEX ROWID TAB10
1 INDEX RANGE SCAN OF XAK_TAB10 (NONUNIQUE)
1 TABLE ACCESS BY INDEX ROWID TAB10
2 INDEX RANGE SCAN OF XAK_TAB10 (NONUNIQUE)
SELECT * FROM TAB1
WHERE 지역 = '서울'
AND 구분 IN ('3','1')
AND 발생일자 BETWEEN '19980601' AND '19980602'
SELECT * FROM TAB1
WHERE 지역 = '서울'
AND 구분 IN ('3','1')
AND 발생일자 IN ('19980601','19980602')
CONCATENATION
TABLE ACCESS (BY ROWID) OF 'TAB1'
INDEX (RANGE SCAN) OF 'INDEX1' (NON-UNIQUE)
TABLE ACCESS (BY ROWID) OF 'TAB1'
INDEX (RANGE SCAN) OF 'INDEX1' (NON-UNIQUE)
#- SC_MONTH_CNTR
#- \------------\-
#- Rows=1,044,101 Blocks=14,343
#- Empty Blocks=1,017 Avg Space=855
#- Chain Count=0 Avg Row Length=96
#- Avg Space Freelist Blocks=0 Freelist Blocks=0
#- Sample Size=187,890 Last Analyze=2007/12/17
\-
#- XPKSC_MONTH_CNTR
#- : BL_ON_YY + BL_ON_MM + SC_TP + SC_NO + SC_NO_SPLIT + SC_SVC_SCP + POR_RGN + POL_RGN + POD_RGN + DEL_RGN + POR_CNT_CD
#- + POL_CNT_CD + POD_CNT_CD + DEL_CNT_CD + CMDT_REP
#- Type=NORMAL, Uniq=YES, Distinct=1,059,520, Rows=1,059,520, Last Analyze=2007/12/17
#-
#-
#- BL_ON_YY NOT NULL VARCHAR2(4) 10 1
#- BL_ON_MM NOT NULL VARCHAR2(3) 12 1
#- SC_TP NOT NULL VARCHAR2(3) 199 1
#- SC_NO NOT NULL VARCHAR2(5) 12,761 1
#- SC_NO_SPLIT NOT NULL VARCHAR2(2) 2 1
\- 테이블 정보의 Point 는 INDEX 중에서 가장 중요한 칼럼은 SC_NO 라는 것입니다.
\- 이것만 체크하시구 WHERE 절에 따른 Access/Fiter Predicates 를 체크 해보셔요
1.
select * from SC_MONTH_CNTR
where BL_ON_YY = '1999'
and BL_ON_MM='Apr'
and SC_TP='CWN'
and SC_NO ='09808';
\- Access Prdicates
"BL_ON_YY"='1999' AND "BL_ON_MM"='Apr' AND "SC_TP"='CWN' AND "SC_NO"='09808'
\- Fiter Predicates
null
2.
select * from SC_MONTH_CNTR
where BL_ON_YY = '1999'
and BL_ON_MM='Apr'
and SC_TP='CWN'
\- Access Prdicates
"BL_ON_YY"='1999' AND "BL_ON_MM"='Apr' AND "SC_TP"='CWN'
\- Fiter Predicates
null
3.
select * from SC_MONTH_CNTR
where BL_ON_YY = '1999'
and BL_ON_MM='Apr'
and SC_TP='CWN'
and to_char(SC_NO) ='09808';
\- Access Prdicates
"BL_ON_YY"='1999' AND "BL_ON_MM"='Apr' AND "SC_TP"='CWN'
\- Fiter Predicates
"SC_NO"='09808'
4.
select * from SC_MONTH_CNTR
where BL_ON_YY = '1999'
and BL_ON_MM='Apr'
and to_char(SC_TP)='CWN'
and SC_NO ='09808';
\- Access Prdicates
"BL_ON_YY"='1999' AND "BL_ON_MM"='Apr' AND "SC_NO"='09808'
\- Fiter Predicates
"SC_NO"='09808' AND "SC_TP"='CWN'
## 참고
From 9i, Oracle introduced the columns filter_predicates and access_predicates
into the plan_table (and corresponding v$sql_plan dynamic performance view)
used for reporting execution plans.
These two columns are extremely helpful for checking why the optimizer isn't
doing what you expect, and they merit a little description.
As a quick approximation, though, you could say that
the access_predicates tells you how Oracle is getting into a table, or joining two tables;
the filter_predicates tells you how Oracle is discarding the irrelevant data items
(which could be table rows or index entries) after getting into an object.
dbms_xplan.display shows the predicates by default.
- 강좌 URL : http://www.gurubee.net/lecture/2499
- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.