Part 1 ORACLE│173 SQL 튜닝에 Dictionary View 활용하기 - Part2 ㈜엑셈 컨설팅본부/DB컨설팅팀 정 동기 개요 SQL 성능을 개선하기 위해서는 판단할 수 있는 근거를 수집하는 작업이 중요하다. SQL 에 사용 된 관련 테이블 정보 및 인덱스 정보들을 수집하여 종합적으로 판단 해야만 좀더 효율적인 성능 개선을 이끌어 낼 수 있기 때문이다. 오라클은 이러한 정보들을 Dictionary View 를 통해서 사 용자에게 전달 하고 있다. 그 중 이번 화이트 페이퍼에서는 테이블과 인덱스 관련 정보를 토대로 SQL 성능 개선에 어떻게 활용되는 지를 서술하고 있다. 테이블, 인덱스 통계를 활용 개선 사례 테이블과 인덱스 관련 정보들은 Dictionary View 를 통해서 살펴 볼 수 있다. 오라클은 DBA_TABLES, DBA_TAB_COLUMNS, DBA_INDEXES, DBA_IND_COLUMNS, DBA_IND_EXPRESSIONS 의 View 들을 통해서 관련 정보들을 검색 활용 할 수 있도록 제공하 고 있다. 그렇다면 테스트를 통해 해당 View 들이 어떻게 활용 되는지를 알아 보도록 하자. 인덱스 효율성 판단 사례 SELECT c1 , c2 , c3 , c4 , c5 , c6 FROM dict_view_t1 t WHERE c2 = 'B' AND c3 = '11' AND c4 = 'RED'
2.
174│2013 기술백서 WhitePaper AND c5 = '1981' AND C1 = 1 ------------------------------------------------------------------------------------- | Id | Operation | Name |Starts| E-Rows | A-Rows | A-Time | ------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 1 | 00:00:00.02 | |* 1 | TABLE ACCESS FULL|DICT_VIEW_T1 | 1 | 1 | 1 | 00:00:00.02 | ------------------------------------------------------------------------------------- 해당 SQL 의 실행 계획을 살펴 보면 총 추출 건수 가 1 건으로 매우 적지만 TABLE FULL SCAN 을 통하여 정보를 추출하고 있으므로 효율적인지를 판단해 볼 필요성이 있다. 그렇다면 TABLE FULL SCAN 이 효율적인 것인지 그렇지 않다면 해당 TABLE 에 적합한 인덱스가 존재 하는지, 인덱스가 존재 한다면 어떠한 인덱스가 효율적인 지를 따져봐야 할 것이다. 오라클은 관련 Dictionary View 를 통해서 해당 자료들을 제공하고 있다. 우선 테이블 인덱스 존재 여부는 DBA_INDEXES 를 통해서 확인 가능하다. [Script 3 수행 결과] INDEX_NAME U TABLESPACE DISTINCT CLUSTERING FACTOR BLEVEL LEAF_BLK --------------------------- - ---------- --------- ------------------ ------ --------- DICT_VIEW_T1_IDX_01(SH) N USERS 1000000 3377 2 2226 DICT_VIEW_T1_IDX_02(SH) N USERS 10 33770 2 3540 또한 해당 인덱스의 구성 칼럼 정보들은 DBA_IND_COLUMNS 를 통해서 살펴볼 수 있다. [Script 4 수행 결과] INDEX_NAME TYPE U COLUMN LIST -------------------- ---- -- -------------- DICT_VIEW_T1_IDX_01 NORM N C1 DICT_VIEW_T1_IDX_02 NORM N C2, C3, C4, C5 그리고 인덱스 구성 칼럼의 CARDINALITY 나 DISTINCT VALUE 등을 살펴 보기 위해서는 DBA_TABLES 와 DBA_TAB_COLUMNS 를 통해서 관련 정보를 얻을 수 있다.
3.
Part 1 ORACLE│175 CARDINALITY = ( DBA_TABLES.NUM_ROWS – DBA_TAB_COLUMN.NUM_NULLS ) / DBA_TAB_COLUMNS.NUM_DISTINCT [활용 Script 1 결과] TABLE NAME TABLESPACE NAME NUM_ROWS DEGREE BLOCKS ---------------- --------------- -------- ------ ------ DICT_VIEW_T1(SH) USERS 1000000 1 3439 [활용 Script 2 결과] COLUMN_NAME DATA_TYPE DATALEN NN DISTINCT DENSITY NUM_NULLS BUCKET SAMPLE_SIZE ------------ -------- ---------- -- --------- ----------- ---------- ------ ---------- C1 NUMBER 22 N 1000000 0.000001000 0 1 1000000 C2 VARCHAR2 1 Y 2 0.500000000 0 1 1000000 C3 NUMBER 22 Y 10 0.100000000 0 1 1000000 C4 VARCHAR2 5 Y 5 0.200000000 0 1 1000000 C5 NUMBER 22 Y 10 0.100000000 0 1 1000000 이렇게 해당 Dictionary View 을 통해서 관련 정보들을 제공 받을 수 있다. 우리는 이러한 정보 들을 활용하여 성능 문제를 개선하기 위한 판단 근거로 활용 할 수 있다. 그렇다면 해당 SQL 의 관련 정보들을 활용하여 효율성을 판단해 보도록 하자. 먼저 SQL 의 WHERE 조건 절을 살펴 보 면 검색 조건으로 C1 ~C5 까지 존재 한다. 또한 TABLE DICT_VIEW_T1 에는 2 개의 인덱스가 존재하는 것을 Dictionary View 를 통해서 확인 하였다. 먼저 2 개의 인덱스 DICT_VIEW_T1_IDX_01, DICT_VIEW_T1_IDX_02 중 어떠한 인덱스가 효율적인 지를 판단 해 보도록 하자. 인덱스 DICT_VIEW_T1_IDX_01 은 칼럼 C1 으로 구성되어 있다. C1 의 CARDINALITY 를 살펴보면 (1000000 – 0) / 1000000 = 1 로 매우 효율적인 것을 확인 할 수 있다. 즉 TABLE DICT_VIEW_T1 의 NUM_ ROWS 값이 1000000 이고 인덱스 DICT_VIEW_T1_IDX_01 의 DISTINCT 값이 1000000 이므로 인덱스 평균 추출 건수가 (1000000/1000000 = 1) 약 1 건이라는 것을 판단 할 수 있다. 이번에는 인덱스 DICT_VIEW_T1_IDX_02 의 효율성을 확인해 보도록 하자. DICT_VIEW_T1_IDX_02 의 구성 칼럼은 C2, C3, C4, C5 로 구성되어 있다. 인덱스 DICT_VIEW_T1_IDX_02 구성 칼럼에 각각 의 CARDINALITY 는 C2 =(10000000 – 0) / 2 = 5000000, C3 =(10000000 – 0) / 10 =
4.
176│2013 기술백서 WhitePaper 1000000, C4 = (10000000 – 0) / 5 = 2000000, C5 = (10000000 – 0) / 10 = 1000000 이다. 인덱스 DICT_VIEW_T1_IDX_02 구성 칼럼의 CARDINALITY 는 C1 칼럼에 비해 매우 비효율 적인 것을 확인 할 수 있다. 다시 말해서 TABLE 의 NUM_ROWS 값이 1000000 이고 인 덱스 DICT_VIEW_T1_IDX_02 의 DISTINCT 값이 10 이므로 1000000/10 = 100000 이므 로 인덱스 평균 추출 건수가 약 100000 건으로 효율적이지 않다는 것을 확인 할 수 있다. 다시 말해서 인덱스 DICT_VIEW_T1_IDX_01 이 훨씬 효율적이라는 것을 판단 할 수 있다. 그렇다면 실제로 그러한지 DATA 를 통해서 확인해 보도록 하자. SELECT COUNT( * ) TOTAL_ROWS, COUNT( DISTINCT c1 ) COL_NDV --- 인덱스 DICT_VIEW_T1_IDX_01 의 구성 칼럼 FROM dict_view_t1 TOTAL_ROWS COL_NDV ---------- ------- 1000000 1000000 DICT_VIEW_T1_IDX_01 활용 시 실제 DATA 를 살펴보면 TABLE 총 ROW 수 1000000, 인덱 스 구성 칼럼 C1 의 DISTINCT 값 1000000 이므로 C1 조건으로 검색할 경우 인덱스를 통한 평 균 추출 건수가 1 건 일 것으로 예측 할 수 있으며 Dictionary View 를 통해서 살펴본 것과 동일 결과를 나타내는 것을 살펴 볼 수 있다. SELECT COUNT( * ) TOTAL_ROWS, COUNT( DISTINCT c2||c3||c4||c5 ) COL_NDV --- 인덱스 DICT_VIEW_T1_IDX_02 의 구성 칼럼 FROM dict_view_t1 TOTAL_ROWS COL_NDV ---------- ------- 1000000 10 DICT_VIEW_T1_IDX_02 활용 시 실제 DATA 를 살펴보면 TABLE 총 ROW 수 1000000, 인덱 스 구성 칼럼 C2, C3, C4, C5 의 DISTINCT 값이 10 이므로 C2, C3, C4, C5 조건으로 검색할 경우 인덱스를 통한 평균 추출 건수가 100000 건 예측 할 수 있으며 Dictionary View 를 통해 서 살펴본 것과 동일 결과를 나타내는 것을 살펴 볼 수 있다. 다시 말해 인덱스 DICT_VIEW_T1_IDX_01 활용 시 1 번의 TABLE RANDOM ACCESS,
5.
Part 1 ORACLE│177 DICT_VIEW_T1_IDX_02 활용 시 최대 100000 번의 TABLE RANDOM ACCESS 가 발생 할 수 있으므로 DICT_VIEW_T1_IDX_01 가 훨씬 효율적이라고 판단 할 수 있다. 마지막으로 해당 인덱스를 활용하여 실제 실행계획을 살펴 보도록 하자. SELECT c1 , c2 , c3 , c4 , c5 , c6 FROM dict_view_t1 t WHERE c2 = 'B' AND c3 = '11' AND c4 = 'RED' AND c5 = '1981' AND c1 = 1 ---------------------------------------------------------------------------------------- | Id | Operation | Name | A-Rows | A-Time | Buffers | ---------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 |00:00:00.01 | 4 | |* 1 | TABLE ACCESS BY INDEX ROWID| DICT_VIEW_T1 | 1 |00:00:00.01 | 4 | |* 2 | INDEX RANGE SCAN |DICT_VIEW_T1_IDX_01 | 1 |00:00:00.01 | 3 | ---------------------------------------------------------------------------------------- 인덱스 DICT_VIEW_T1_IDX_01 를 활용한 SQL 의 실행 계획이다. 인덱스를 통해 1 건을 추출 후 1 번의 TABLE RANDOM ACCESS 가 발생 하였으며 총 4 BLOCKS 를 READ 하였다. 인덱스 구성 칼럼 C1 이 UNIQUE 하므로 인덱스 BLOCK READS 량 또한 매우 적은 것을 알 수 있다. SELECT c1 , c2 , c3 , c4 , c5 , c6 FROM dict_view_t1 t WHERE c2 = 'B' AND c3 = '11' AND c4 = 'RED' AND c5 = '1981' AND c1 = 1
6.
178│2013 기술백서 WhitePaper ---------------------------------------------------------------------------------------- | Id | Operation | Name | A-Rows | A-Time | Buffers | ---------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 |00:00:00.09 | 3715 | |* 1 | TABLE ACCESS BY INDEX ROWID| DICT_VIEW_T1 | 1 |00:00:00.09 | 3715 | |* 2 | INDEX RANGE SCAN | DICT_VIEW_T1_IDX_02 | 100K |00:00:00.89 | 338| ---------------------------------------------------------------------------------------- CLUSTERING FACTOR 가 33770 이므로 약 30 ROW 당 1 TABLE RANDOM ACCESS 이므로 BLOCK READS 량 감소 인덱스 DICT_VIEW_T1_IDX_02 를 활용한 SQL 의 실행 계획이다. 인덱스를 통해 100000 건 을 추출 후 약 3715-338 = 3377 번의 TABLE RANDOM ACCESS 가 발생 하였으며 총 3715 BLOCK READS 가 발생하였으며 인덱스 BLOCK READS 량 또한 DICT_VIEW_T1_IDX_01 에 비해서 비효율 적인 것을 알 수 있다. 총 3 가지의 SQL 실행 계획을 정리해 보면, 첫 번째 TABLE FULL SCAN 하였을 경우 총 3348 BLOCK, 두 번째 인덱스 DICT_VIEW_T1_IDX_01 를 활용 하였을 경우 인덱스 3 BLOCK READS 그리고 1 번의 TABLE RANDOM ACCESS, 세 번째 DICT_VIEW_T1_IDX_02 를 활용 하였을 경우 인덱스 338 BLOCK READS 와 약 3377 번의 TABLE RANDOM ACCESS 가 발생 하고 있다. 즉 Dictionary View 를 통해 살펴 본 결과와 동일하게 인덱스 DICT_VIEW_T1_IDX_01 를 활용 했을 때 가장 효율적이라는 것을 실제 실행계획을 통해서 확 인 할 수 있다. 테이블, 인덱스 Dictionary View 상세 설명 및 활용 스크립트 위의 개선 사례로 보았듯이 Dictionary View에는 SQL성능을 개선하기 위한 판단 자료로 유용 한 View들이 존재 한다. DBA_TABLES, DBA_TAB_COLUMNS, DBA_INDEXES, DBA_IND_COLUMNS, DBA_IND_EXPRESSIONS 등을 활용하여 성능 개선에 유용하게 사용될 수 있다. Note. 문서에서 기술될 Dictionary View 의 버전은 11g R2 버전이다.
7.
Part 1 ORACLE│179 TABLE, INDEX 관련 DBA_* VIEW SQL 성능 이슈에 도움이 되는 TABLE, INDEX 관련 Dictionary View 인 DBA_TABLES, DBA_TAB_COLUMNS, DBA_INDEXES, DBA_IND_COLUMNS, DBA_IND_EXPRESSIONS 에 관하여 자세히 알아보도록 하자. DB A_TABLES DBA_TABLES 는 데이터베이스에 있는 모든 TABLE 에 관한 정보들을 설명한 VIEW 다. 이 View 의 중요 컬러 정보는[표 1]와 같다. Column Name Data Type Descrption OWNER VARCHAR2(30) TABLE 의 OWNER TABLE_NAME VARCHAR2(30) TABLE 의 이름 TABLESPACE_NAME VARCHAR2(30) TABLE 이 속해 있는 TABLESAPCE 명 PCT_FREE NUMBER 블록의 최소 여유 공간 (백분율) PCT_USED NUMBER 블록에 대해 유지하려는 사용 공간의 최소 치(백 분율) NEXT_EXTENT NUMBER 다음 extent 의 Size MIN_EXTENTS NUMBER 세그먼트에 허용 된 extents 의 최소 수 NUM_ROWS* NUMBER TABLE ROW 수 BLOCKS* NUMBER TABLE 에 사용 된 DATA BLOCK 수 DEGREE NUMBER TABLE 을 병렬 처리 시 사용되는 Process 수 PARTITIONED VARCHAR2 파티션 TABLE 인지를 나타낸다. LAST_ANALYZED DATE 마지막 통계정보가 생성된 날짜 AVG_SPACE NUMBER DATA BLOCK 의 평균 Free Space AVG_ROW_LEN NUMBER TABLE ROW 의 평균 길이(In Bytes) EMPTY_BLOCKS NUMBER TABLE 에 비어있는 BLOCK 수 [표 1] DBA_TABLES 중요 칼럼 Script 1> SELECT table_name||'(' ||owner||')' || CHR( 10 ) ||tablespace_name ||decode( partitioned , 'YES' , '* Partitioned ' , '' ) ||decode( TEMPORARY , 'Y' , '* Temporary ' , '' ) AS "TAB_INFO" , TRUNC( num_rows ) num_rows ,
8.
180│2013 기술백서 WhitePaper avg_row_len , blocks || CHR( 10 ) || empty_blocks AS "BLK_INFO" , TRIM( degree ) degree , avg_space , chain_cnt , pct_free || '/' || pct_used || '/' || pct_increase pct , ini_trans || '/' ||max_trans tran , decode( SIGN( FLOOR( initial_extent/1024/1024 ) ) , 1 , ROUND( initial_extent/1024/1024 ) ||'m' , ROUND( initial_extent/1024 ) ||'k' ) || '/' || decode( SIGN( FLOOR( next_extent/1024/1024 ) ) , 1 , ROUND( next_extent/1024/1024 ) ||'m' , ROUND( next_extent/1024 ) ||'k' ) || CHR( 10 ) || min_extents ||'/' || decode( max_extents , 2147483645 , 'Unlimit' , max_extents ) inext , FREELISTS || '/' || freelist_groups free , TO_CHAR( last_analyzed , 'yyyy-mm-dd:hh24:mi:ss' ) last_analFROM dba_tables WHERE table_name = UPPER( TRIM( :table_name ) ) AND owner = UPPER( TRIM( :schname ) ) [Scrpit 1] DBA_TABLES 활용 DBA_TAB_COLUMNS DBA_TAB_COLUMNS 는 데이터베이스에 있는 Clusters, Tables, Views 의 모든 칼럼 정보들 을 담고 있다. 이 View 의 중요 칼럼 정보는 [표 2]와 같다. Column Name Data Type Descrption OWNER VARCHAR2(30) TABLE, VIEW, CLUSTER 의 OWNER TABLE_NAME VARCHAR2(30) TABLE, VIEW, CLUSTER 의 이름 COLUMN_NAME VARCHAR2(30) COLUMN 의 이름 DATA_TYPE VARCHAR2(106) COLUMN 의 DATA TYPE DATA_LENGTH NUMBER COLUMN 의 길이(In bytes) NULLABLE VARCHAR2(1) NULL 사용가능 여부 NUM_DISTINCT NUMBER COLUMN 의 DISTINCT 값(DATA VALUE 의 종류 수) DENSITY NUMBER COLUMN 의 DENSITY 값 NUM_NULLS NUMBER COLUMN 에 포함 된 NULL 의 수 SAMPLE_SIZE NUMBER 통계정보 수집 시 사용되는 SAMPLE SIZE LAST_ANALYZED DATE 마지막 통계정보가 생성된 날짜
9.
Part 1 ORACLE│181 HISTOGRAM VARCHAR2 히스토그램의 TYPE(NONE, FREQUENCY, HEIFHT BALANCED) [표 2] DBA_TAB_COLUMNS 중요 칼럼 Script 2 > SELECT column_name , data_type , data_length , decode( data_precision || '/' || data_scale , '/' , NULL , data_precision || '/' || data_scale ) dpds , nullable nn , num_distinct , density , num_nulls , num_buckets , sample_size , TO_CHAR( last_analyzed , 'yyyy-mm-dd' ) last_anal FROM dba_tab_columns WHERE owner = UPPER( TRIM( :schname ) ) AND table_name = UPPER( TRIM( :table_name ) ) [Scrpit 2] DBA_TAB_COLUMNS 활용 DBA_INDEXES DBA_INDEXES 는 데이터베이스에 존재하는 모든 인덱스 정보를 담고 있다. 이 View 의 중요 칼럼 정보는 [표 3]와 같다. Column Name Data Type Descrption OWNER VARCHAR2(30) INDEX 의 OWNER INDEX_NAME VARCHAR2(30 INDEX 의 NAME INDEX_TYPE VARCHAR2(27) INDEX 의 TYPE (NORMAL, BITMAP, FUNCTION- BASED NORMAL 등) TABLE_OWNER VARCHAR2(30) INDEX 를 소유하고 있는 TABLE 의 OWNER TABLE_NAME VARCHAR2(30) INDEX 를 소유하고 있는 TABLE 의 이름 TABLE_TYPE CHAR(5) INDEX OBJECT 의 TYPE (NEXT OBJECT, INDEX, TABLE 등) UNIQUENESS VARCHAR2(9) INDEX 가 UNIQUE OR NONUNIQUE 인지 식별 TABLESPACE_NAME VARCHAR2(30) INDEX 가 포함된 TABLE SPACE 이름
10.
182│2013 기술백서 WhitePaper BLEVEL* NUMBER B-TREE 레벨 값 LEAF_BLOCKS* NUMBER INDEX 의 LEAF BLOCK 의 수 DISTINCT_KEYS* NUMBER INDEX 의 DISTINCT 값 PARTITIONED VARCHAR2(3) INDEX 의 파티션 유무 CLUSTERING_FACTOR NUMBER DATA 가 INDEX ORDER 순으로 모여있는 정도를 나타냄 NUM_ROW NUMBER INDEX 의 총 ROW 수 LAST_ANALYZED DATE 마지막 통계정보가 생성된 날짜 [표 3] DBA_INDEXES 중요 칼럼 Script 3 > SELECT index_name||'(' ||owner||')' index_name , SUBSTR( uniqueness , 1 , 1 ) u , tablespace_name||decode( partitioned , 'YES' , '*Partitioned ' , '' ) ||decode( TEMPORARY , 'Y' , '*Temporary ' , '' ) TABLESPACE , TO_CHAR( TRUNC( num_rows ) ) ||chr( 10 ) ||to_char( distinct_keys ) AS "NUM_ROWS_DISTINCT" , clustering_factor , leaf_blocks || CHR( 10 ) || blevel AS "BLK_INFO" , avg_leaf_blocks_per_key || '/' ||avg_data_blocks_per_key alb_adb , ini_trans || '/' ||max_trans tran , decode( SIGN( FLOOR( initial_extent/1024/1024 ) ) , 1 , ROUND( initial_extent/1024/1024 ) ||'m' , ROUND( initial_extent/1024 ) ||'k' ) || '/' || decode( SIGN( FLOOR( next_extent/1024/1024 ) ) , 1 , ROUND( next_extent/1024/1024 ) ||'m' , ROUND( next_extent/1024 ) ||'k' ) || CHR( 10 ) || min_extents ||'/' || decode( max_extents , 2147483645 , 'unlimit' , max_extents ) inext , FREELISTS || '/' || freelist_groups free , TO_CHAR( last_analyzed , 'yyyy-mm-dd' ) last_anal FROM dba_indexes WHERE table_name = UPPER( TRIM( :table_name ) ) AND table_owner = UPPER( TRIM( :schname ) ) [Scrpit 3] DBA_INDEXES 활용
11.
Part 1 ORACLE│183 DBA_IND_COLUMNS DBA_IND_COLUMNS 는 데이터베이스에 있는 Clusters, Tables, Views 의 모든 인덱스 칼럼 정보들을 담고 있다. 이 View 의 중요 칼럼 정보는 [표 4]와 같다 Column Name Data Type Descrption OWNER VARCHAR2(30) INDEX 의 OWNER INDEX_NAME VARCHAR2(30 INDEX 의 NAME INDEX_TYPE VARCHAR2(27) INDEX 의 TYPE (NORMAL, BITMAP, FUNCTION- BASED NORMAL 등) TABLE_OWNER VARCHAR2(30) INDEX OBJECT 의 소유자(OWNER) COLUMN_POSITION NUMBER INDEX 구성 COLUMN 의 순서 DESCEND VARCHAR2 SORT 상태를 나타냄 [표 4] DBA_IND_COLUMNS 중요 칼럼 Script 4 > SELECT index_name , SUBSTR( index_type , 1 , 4 ) TYPE , SUBSTR( uniqueness , 1 , 1 ) u , ( SELECT MAX( decode( column_position , 1 , column_name ) ) || decode( MAX( decode( column_position , 2 , column_name ) ) , NULL , NULL , ', ' ) || MAX( decode( column_position , 2 , column_name ) ) || decode( MAX( decode( column_position , 3 , column_name ) ) , NULL , NULL , ', ' ) || MAX( decode( column_position , 3 , column_name ) ) || decode( MAX( decode( column_position , 4 , column_name ) ) , NULL , NULL , ', ' ) || MAX( decode( column_position , 4 , column_name ) ) || decode( MAX( decode( column_position , 5 , column_name ) ) , NULL , NULL , ', ' ) || MAX( decode( column_position , 5 , column_name ) ) || decode( MAX( decode( column_position , 6 , column_name ) ) , NULL , NULL , ', ' ) || MAX( decode( column_position , 6 , column_name ) ) || decode( MAX( decode( column_position , 7 , column_name ) ) , NULL , NULL , ', ' ) || MAX( decode( column_position , 7 , column_name ) ) || decode( MAX( decode( column_position , 8 , column_name ) ) , NULL ,
Part 1 ORACLE│185 Column Name Data Type Descrption INDEX_OWNER VARCHAR2(30) INDEX 의 OWNER INDEX_NAME VARCHAR2(30 INDEX 의 NAME TABLE_OWNER VARCHAR2(30) INDEX 를 소유하고 있는 TABLE 의 OWNER TABLE_NAME VARCHAR2(30) INDEX OBJECT 의 NAME COLUMN_EXPRESSION LONG FUNCTION-BASED INDEX COLUMN 의 표현 식 을 나타낸다. COLUMN_POSITION NUMBER INDEX 구성 COLUMN 순서 [표 5] DBA_IND_EXPRESSIONS 중요 칼럼 결론 이번 기술 백서에서는 DBA_TABLES, DBA_TAB_COLUMNS, DBA_INDEXES, DBA_IND_COLUMNS 의 간단한 활용 사례와 각각의 구성 칼럼들에 대하여 알아 보았다. 이처 럼 오라클은 성능 이슈에 활용 할 수 있는 다양한 Dicationary View 들을 제공해 오고 있다. 각 각의 View 들이 갖고 있는 정보들을 숙지하고 활용 한다면 SQL 성능 개선의 판단 자료로 활용 할 수 있을 것이다.