인덱스의 선정
!p32.jpg! (32 페이지 그림)
SQL> SELECT SUM(EMPNO) FROM OC_EMP_1000 WHERE DEPT < 100;
----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 26 | 49 (7)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 26 | | |
|* 2 | TABLE ACCESS FULL| OC_EMP_1000 | 7975 | 202K| 49 (7)| 00:00:01 |
----------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
1074 recursive calls
0 db block gets
428 consistent gets
217 physical reads
0 redo size
430 bytes sent via SQL*Net to client
400 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
19 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> SELECT /*+ INDEX(OC_EMP_1000 OC_EMP_1000_S1) */ SUM(EMPNO) FROM OC_EMP_1000 WHERE DEPT < 100;
-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 26 | 7561 (1)| 00:01:31 |
| 1 | SORT AGGREGATE | | 1 | 26 | | |
| 2 | TABLE ACCESS BY INDEX ROWID| OC_EMP_1000 | 7975 | 202K| 7561 (1)| 00:01:31 |
|* 3 | INDEX RANGE SCAN | OC_EMP_1000_S1 | 7975 | | 23 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
1074 recursive calls
0 db block gets
7840 consistent gets
235 physical reads
0 redo size
430 bytes sent via SQL*Net to client
400 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
19 sorts (memory)
0 sorts (disk)
1 rows processed
10g(10.2.0.4)
-- 분포도 약 10% 테스트 TABLE ACCESS FULL
DROP TABLE OC_EMP_10;
CREATE TABLE OC_EMP_10 AS
SELECT LEVEL AS EMPNO,
ROUND(DBMS_RANDOM.VALUE(1, 10)) AS DEPT
FROM DUAL CONNECT BY LEVEL < 100001;
CREATE INDEX OC_EMP_10_S1 ON OC_EMP_10 (DEPT);
SELECT SUM(EMPNO), COUNT(*) FROM OC_EMP_10 WHERE DEPT = 1;
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 26 | 46 (7)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 26 | | |
|* 2 | TABLE ACCESS FULL| OC_EMP_10 | 5657 | 143K| 46 (7)| 00:00:01 |
--------------------------------------------------------------------------------
-- 분포도 약 1% 테스트 TABLE ACCESS FULL
DROP TABLE OC_EMP_100;
CREATE TABLE OC_EMP_100 AS
SELECT LEVEL AS EMPNO,
ROUND(DBMS_RANDOM.VALUE(1, 100)) AS DEPT
FROM DUAL CONNECT BY LEVEL < 100001;
CREATE INDEX OC_EMP_100_S1 ON OC_EMP_100 (DEPT);
SELECT SUM(EMPNO), COUNT(*) FROM OC_EMP_100 WHERE DEPT = 1;
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 26 | 46 (7)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 26 | | |
|* 2 | TABLE ACCESS FULL| OC_EMP_100 | 495 | 12870 | 46 (7)| 00:00:01 |
---------------------------------------------------------------------------------
-- 분포도 약 0.1% 테스트 INDEX RANGE SCAN
DROP TABLE OC_EMP_1000;
CREATE TABLE OC_EMP_1000 AS
SELECT LEVEL AS EMPNO,
ROUND(DBMS_RANDOM.VALUE(1, 1000)) AS DEPT
FROM DUAL CONNECT BY LEVEL < 100001;
CREATE INDEX OC_EMP_1000_S1 ON OC_EMP_1000 (DEPT);
SELECT SUM(EMPNO), COUNT(*) FROM OC_EMP_1000 WHERE DEPT = 1;
-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 26 | 33 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 26 | | |
| 2 | TABLE ACCESS BY INDEX ROWID| OC_EMP_1000 | 51 | 1326 | 33 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | OC_EMP_1000_S1 | 51 | | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------
9i(9.2.0.1)
-- 분포도 약 10% 테스트 (TABLE ACCESS (FULL))
DROP TABLE OC_EMP_10;
CREATE TABLE OC_EMP_10 AS
SELECT LEVEL AS EMPNO,
ROUND(DBMS_RANDOM.VALUE(1, 10)) AS DEPT
FROM DUAL CONNECT BY LEVEL <= 100001;
CREATE INDEX OC_EMP_10_S1 ON OC_EMP_10 (DEPT);
ANALYZE TABLE OC_EMP_10 COMPUTE STATISTICS;
SELECT SUM(EMPNO), COUNT(*) FROM OC_EMP_10 WHERE DEPT = 1;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=60 Card=1 Bytes=6)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'OC_EMP_10' (Cost=60 Card=10000 Bytes=60000)
-- 분포도 약 1% 테스트 (TABLE ACCESS (FULL))
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=60 Card=1 Bytes=6)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'OC_EMP_100' (Cost=60 Card=1000 Bytes=6000)
-- 분포도 약 0.1% 테스트 (TABLE ACCESS (FULL))
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=64 Card=1 Bytes=7)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'OC_EMP_1000' (Cost=64 Card=100 Bytes=700)
-- 분포도 약 0.05% 테스트 INDEX (RANGE SCAN)
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=50 Card=1 Bytes=7)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (BY INDEX ROWID) OF 'OC_EMP_2000' (Cost=50 Card=50 Bytes=350)
3 2 INDEX (RANGE SCAN) OF 'OC_EMP_2000_S1' (NON-UNIQUE) (Cost=3 Card=50)
8i(8.1.6.0)
-- 분포도 약 1% 테스트 (TABLE ACCESS (FULL))
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=28 Card=1 Bytes=6)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'OC_EMP_100' (Cost=28 Card=1001 Bytes=6006)
-- 분포도 약 0.1% 테스트 (TABLE ACCESS (FULL))
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=29 Card=1 Bytes=7)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'OC_EMP_1000' (Cost=29 Card=101 Bytes=707)
-- 분포도 약 0.05% 테스트 (TABLE ACCESS (FULL))
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=30 Card=1 Bytes=7)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'OC_EMP_2000' (Cost=30 Card=51 Bytes=357)
-- 분포도 약 0.02% 테스트 INDEX (RANGE SCAN)
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=20 Card=1 Bytes=7)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (BY INDEX ROWID) OF 'OC_EMP_5000' (Cost=20 Card=21 Bytes=147)
3 2 INDEX (RANGE SCAN) OF 'OC_EMP_5000_S1' (NON-UNIQUE) (Cost=1 Card=21)
!p34.jpg! (34 페이지 그림)
DROP TABLE OC_EMP_MERGE;
CREATE TABLE OC_EMP_MERGE AS
SELECT LEVEL AS EMPNO,
ROUND(DBMS_RANDOM.VALUE(1, 1000)) AS DEPT1,
ROUND(DBMS_RANDOM.VALUE(1, 1000)) AS DEPT2
FROM DUAL CONNECT BY LEVEL <= 100001;
CREATE INDEX OC_EMP_MERGE_S1 ON OC_EMP_MERGE (DEPT1);
CREATE INDEX OC_EMP_MERGE_S2 ON OC_EMP_MERGE (DEPT2);
SELECT AVG(EMPNO)
FROM OC_EMP_MERGE
WHERE DEPT1 = 62
AND DEPT2 = 231;
-----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 39 | 5 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 39 | | |
| 2 | TABLE ACCESS BY INDEX ROWID | OC_EMP_MERGE | 13 | 507 | 5 (0)| 00:00:01 |
| 3 | BITMAP CONVERSION TO ROWIDS | | | | | |
| 4 | BITMAP AND | | | | | |
| 5 | BITMAP CONVERSION FROM ROWIDS| | | | | |
|* 6 | INDEX RANGE SCAN | OC_EMP_MERGE_S1 | | | 1 (0)| 00:00:01 |
| 7 | BITMAP CONVERSION FROM ROWIDS| | | | | |
|* 8 | INDEX RANGE SCAN | OC_EMP_MERGE_S2 | | | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
1136 recursive calls
0 db block gets
278 consistent gets
232 physical reads
0 redo size
424 bytes sent via SQL*Net to client
400 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
19 sorts (memory)
0 sorts (disk)
1 rows processed
SELECT /*+ INDEX(OC_EMP_MERGE OC_EMP_MERGE_S1) */ AVG(EMPNO)
FROM OC_EMP_MERGE
WHERE DEPT1 = 62
AND DEPT2 = 231;
------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 39 | 129 (0)| 00:00:02 |
| 1 | SORT AGGREGATE | | 1 | 39 | | |
|* 2 | TABLE ACCESS BY INDEX ROWID| OC_EMP_MERGE | 13 | 507 | 129 (0)| 00:00:02 |
|* 3 | INDEX RANGE SCAN | OC_EMP_MERGE_S1 | 206 | | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
738 recursive calls
0 db block gets
318 consistent gets
242 physical reads
0 redo size
424 bytes sent via SQL*Net to client
400 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
15 sorts (memory)
0 sorts (disk)
1 rows processed
SELECT /*+ AND_EQUAL(OC_EMP_MERGE OC_EMP_MERGE_S1 OC_EMP_MERGE_S2) */ AVG(EMPNO)
FROM OC_EMP_MERGE
WHERE DEPT1 = 62
AND DEPT2 = 231;
------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 39 | 2 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 39 | | |
|* 2 | TABLE ACCESS BY INDEX ROWID| OC_EMP_MERGE | 13 | 507 | 2 (0)| 00:00:01 |
| 3 | AND-EQUAL | | | | | |
|* 4 | INDEX RANGE SCAN | OC_EMP_MERGE_S2 | 181 | | 1 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | OC_EMP_MERGE_S1 | 206 | | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
1136 recursive calls
0 db block gets
540 consistent gets
232 physical reads
0 redo size
424 bytes sent via SQL*Net to client
400 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
19 sorts (memory)
0 sorts (disk)
1 rows processed
- EMP.DEPT 는 20% 의 분포도로 가정
- 전체범위
SELECT DEPT, SUM(SAL)
FROM EMP
WHERE JOB = 'SALESMAN'
GROUP BY DEPT;
- 전체범위 (JOB_INDEX 없음)
SELECT DEPT, ENAME, SAL
FROM EMP
WHERE JOB = 'SALESMAN'
ORDER BY JOB DESC;
- 부분범위처리 (수행속도향상)
SELECT /*+ INDEX_DESC(A JOB_INDEX) */ DEPT, ENAME, SAL
FROM EMP A
WHERE JOB = 'SALESMAN';
DROP TABLE OC_EMP_P51;
CREATE TABLE OC_EMP_P51 AS
SELECT LEVEL AS EMPNO,
ROUND(DBMS_RANDOM.VALUE(1, 5)) AS DEPT
FROM DUAL CONNECT BY LEVEL <= 10000;
SELECT EMPNO, DEPT
FROM OC_EMP_P51
WHERE DEPT = 1
ORDER BY DEPT DESC;
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1253 | 32578 | 6 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| OC_EMP_P51 | 1253 | 32578 | 6 (0)| 00:00:01 |
--------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
999 recursive calls
0 db block gets
282 consistent gets
39 physical reads
0 redo size
22298 bytes sent via SQL*Net to client
1313 bytes received via SQL*Net from client
85 SQL*Net roundtrips to/from client
18 sorts (memory)
0 sorts (disk)
1253 rows processed
CREATE INDEX OC_EMP_P51_S1 ON OC_EMP_P51 (DEPT);
SELECT /*+ INDEX_DESC(OC_EMP_P51 OC_EMP_P51_S1) */
EMPNO, DEPT
FROM OC_EMP_P51
WHERE DEPT = 1;
----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1253 | 32578 | 15 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID | OC_EMP_P51 | 1253 | 32578 | 15 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN DESCENDING| OC_EMP_P51_S1 | 1253 | | 4 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
1054 recursive calls
0 db block gets
384 consistent gets
45 physical reads
0 redo size
22298 bytes sent via SQL*Net to client
1313 bytes received via SQL*Net from client
85 SQL*Net roundtrips to/from client
19 sorts (memory)
0 sorts (disk)
1253 rows processed
(on) 선 인덱스 후 어플리케이션
이 자료는 (주)엔코아정보컨설팅 에서 발행된 대용량 데이터베이스 솔루션 I 의 내용을 참고 했습니다.
- 강좌 URL : http://www.gurubee.net/lecture/2465
- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.