sql 튜닝에 dictionary view 활용하기 part2_wh oracle

13
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'

Post on 22-Jan-2017

149 views

Category:

Education


2 download

TRANSCRIPT

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'

174│2013 기술백서 White Paper

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를 통해서 관련 정보를 얻을 수 있다.

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 =

176│2013 기술백서 White Paper

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,

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

178│2013 기술백서 White Paper

----------------------------------------------------------------------------------------

| 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버전이다.

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 ,

180│2013 기술백서 White Paper

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 마지막 통계정보가 생성된 날짜

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 이름

182│2013 기술백서 White Paper

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 활용

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 ,

184│2013 기술백서 White Paper

NULL , ', ' ) ||

MAX( decode( column_position , 8 , column_name ) ) ||

decode( MAX( decode( column_position , 9 , column_name ) ) , NULL ,

NULL , ', ' ) ||

MAX( decode( column_position , 9 , column_name ) ) ||

decode( MAX( decode( column_position , 10 , column_name ) ) , NULL ,

NULL , ', ' ) ||

MAX( decode( column_position , 10 , column_name ) ) ||

decode( MAX( decode( column_position , 11 , column_name ) ) , NULL ,

NULL , ', ' ) ||

MAX( decode( column_position , 11 , column_name ) ) ||

decode( MAX( decode( column_position , 12 , column_name ) ) , NULL ,

NULL , ', ' ) ||

MAX( decode( column_position , 12 , column_name ) ) ||

decode( MAX( decode( column_position , 13 , column_name ) ) , NULL ,

NULL , ', ' ) ||

MAX( decode( column_position , 13 , column_name ) ) ||

decode( MAX( decode( column_position , 14 , column_name ) ) , NULL ,

NULL , ', ' ) ||

MAX( decode( column_position , 14 , column_name ) ) ||

decode( MAX( decode( column_position , 15 , column_name ) ) , NULL ,

NULL , ', ' ) ||

MAX( decode( column_position , 15 , column_name ) )

FROM all_ind_columns col

WHERE col.index_name = a.index_name

AND col.table_owner = a.table_owner

AND col.table_name = a.table_name

) AS column_list

FROM dba_indexes a

WHERE a.table_name = UPPER( TRIM( :table_name ) )

AND a.table_owner= UPPER( TRIM( :schname ) )

ORDER BY index_name

[Scrpit 4] DBA_IND_COLUMNS 활용

DBA_IND_EXPRESSIONS

DBA_IND_EXPRESSIONS는 데이터베이스의 Clusters, Tables, Views있는 모든

FUNCTION-BASE 인덱스 관련 정보를 담고 있다. 이 View의 중요 칼럼 정보는 [표 5]와 같다

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 성능 개선의 판단 자료로 활용

할 수 있을 것이다.