DATA 전문가로 가는 길

[Oracle] Not Null 제약 조건에 따른 인덱스 실행 계획 본문

Data Architecture/Tunning

[Oracle] Not Null 제약 조건에 따른 인덱스 실행 계획

EstenPark 2015. 12. 23. 10:50

오라클 옵티마이저가 수행할 때 제약 설정에 따라서 인덱스 사용/비사용 할 수 있습니다. 우리가 말하는 오라클 옵티마이저 행동 중에서 영향을 미치는 요소 중에 하나 입니다.

/* EST_OBJECT 테이블의 OBJECT_NAME 컬럼에 OBJECT_TYPE이 INDEX가 아닌 나머지는 NULL로 처리 합니다. */
CREATE TABLE EST_OBJECT AS
SELECT   A.OWNER
        ,CASE 
          WHEN A.OBJECT_TYPE = 'INDEX' THEN A.OBJECT_NAME
          ELSE NULL
         END AS OBJECT_NAME 
FROM     DBA_OBJECTS A
; 

/* 인덱스 생성 */
CREATE INDEX EST_OBJECT_IDX01 ON EST_OBJECT ( OBJECT_NAME );

/* EST_OBJECT.OBJECT_NAME 컬럼의 NOT NULL 확인 */ 
SELECT    A.TABLE_NAME, A.COLUMN_NAME, A.NULLABLE
FROM      DBA_TAB_COLS A
WHERE     A.TABLE_NAME = 'EST_OBJECT'
AND       A.COLUMN_NAME = 'OBJECT_NAME'
;
[결과]
TABLE_NAME:   EST_OBJECT
COLUMN_NAME:  OBJECT_NAME
NULLABLE:     Y

 
/* 힌트를 사용하여 INDEX FULL SCAN을 유도 */
SELECT    /*+ INDEX (A EST_OBJECT_IDX01) */
          OBJECT_NAME, COUNT(*)
FROM      EST_OBJECT A      
GROUP BY  OBJECT_NAME
;

[실행계획]
------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation          | Name       | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |            |      1 |        |       |    42 (100)|          |    501 |00:00:00.05 |     137 |       |       |          |
|   1 |  HASH GROUP BY     |            |      1 |  68155 |  4392K|    42  (10)| 00:00:01 |    501 |00:00:00.05 |     137 |  7808K|  2119K|          |
|   2 |   TABLE ACCESS FULL| EST_OBJECT |      1 |  68155 |  4392K|    39   (3)| 00:00:01 |  73599 |00:00:00.02 |     137 |       |       |          |
------------------------------------------------------------------------------------------------------------------------------------------------------


위 내용을 보시면 힌트를 사용해서 INDEX를 사용할 수 있게 유도 했지만, TABLE FULL SCAN으로 나오는 것을 볼 수 있습니다. 이러한 이유는 해당 컬럼의 제약 조건이 NULL을 허용하게 설정 되어 있으면 정상적으로 인덱스를 사용할 수 없게 되는 것입니다. 따라서 아래는 NOT NULL 제약 설정을 하고, 동일한 쿼리를 다시 수행 해보겠습니다.

/* EST_OBJECT 테이블에서 OBJECT_NAME 컬럼의 값이 NULL인 데이터를 모두 삭제 합니다.*/
DELETE   EST_OBJECT A
WHERE    a.OBJECT_NAME IS NULL
;

COMMIT;

/* 힌트를 사용하여 INDEX FULL SCAN을 유도 */
SELECT    /*+ INDEX (A EST_OBJECT_IDX01) */
          OBJECT_NAME, COUNT(*)
FROM      EST_OBJECT A      
GROUP BY  OBJECT_NAME
;

[실행계획]
------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation          | Name       | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |            |      1 |        |       |    42 (100)|          |    501 |00:00:00.05 |     137 |       |       |          |
|   1 |  HASH GROUP BY     |            |      1 |  68155 |  4392K|    42  (10)| 00:00:01 |    501 |00:00:00.05 |     137 |  7808K|  2119K|          |
|   2 |   TABLE ACCESS FULL| EST_OBJECT |      1 |  68155 |  4392K|    39   (3)| 00:00:01 |  73599 |00:00:00.02 |     137 |       |       |          |
------------------------------------------------------------------------------------------------------------------------------------------------------

/* 컬럼 NOT NULL 제약 설정 */
ALTER TABLE EST_OBJECT MODIFY (OBJECT_NAME VARCHAR2(30) NOT NULL);

/* 힌트를 사용하여 INDEX FULL SCAN을 유도 */
SELECT    /*+ INDEX (A EST_OBJECT_IDX01) */
          OBJECT_NAME, COUNT(*)
FROM      EST_OBJECT A      
GROUP BY  OBJECT_NAME
;

[실행계획]
------------------------------------------------------------------------------------------
| Id  | Operation            | Name             | E-Rows |E-Bytes| Cost (%CPU)| E-Time   |
------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |                  |   5932 |    98K|    25   (0)| 00:00:01 |
|   1 |  SORT GROUP BY NOSORT|                  |   5932 |    98K|    25   (0)| 00:00:01 |
|   2 |   INDEX FULL SCAN    | EST_OBJECT_IDX01 |   5932 |    98K|    25   (0)| 00:00:01 |
------------------------------------------------------------------------------------------

너무나 간단한 문제라고 생각 할 수 있지만, 힌트를 사용해도 인덱스를 제대로 활용하지 못할 때 오라클 옵티마이저가 가지고 있는 독특한 개념 때문에 그럴 수 있습니다. 저 또한 이러한 이유로 원인을 찾아내지 못 한 적 있었습니다. 실습을 통해서 확인 해보시면 바로 알 수 있는 부분입니다.




Comments