Clustering Factor (CF)
from Practical OWI | exem | exem
1.
정의
CLUSTERING FACTOR - 모든 인덱스 로우에 대해 순차적으로 데이터(테이블) 로우를 엑세스할 때 DISK READ를 일으켜 읽어 들어야 하는 총 데이터 블록의 수
2.
특징
A.
CLUSTERING
FACTOR 의 값은 NUMBER 타입이며
블록수보다 작을 수 없다.
아래의 쿼리에서는 해당 INDEX 가 사용하는 블록의 수를 조회해 보았다.
SQL> select segment_name, blocks
from dba_segments
where segment_name = 'TEST_ID1_IDX’
SEGMENT_NAME BLOCKS
-------------------- ----------
TEST_ID1_IDX 512
아래의 쿼리에서는 해당 인덱스의 clustering_factor를 조회해 보았다.
SQL> select index_name,clustering_factor
2 from dba_indexes
3 where index_name = 'TEST_ID1_IDX';
INDEX_NAME CLUSTERING_FACTOR
------------------------------ -----------------
TEST_ID1_IDX 690
B.
INDEX를 REBUILD 해도
TABLE의 CF가 개선되지 않으면 성능개선에 큰 영향을 줄 수 없다.
SQL> select index_name,clustering_factor
2 from dba_indexes
3 where index_name = 'TEST_ID1_IDX';
INDEX_NAME CLUSTERING_FACTOR
------------------------------ -----------------
TEST_ID1_IDX 690
SQL> alter index test.test_id1_idx rebuild;
Index altered.
SQL> select index_name, clustering_factor
2 from dba_indexes
3 where index_name = 'TEST_ID1_IDX';
INDEX_NAME CLUSTERING_FACTOR
------------------------------ -----------------
TEST_ID1_IDX 690
SQL> select index_name,status
2 from dba_indexes
3 where index_name = 'TEST_ID1_IDX';
INDEX_NAME STATUS
------------------------------ --------
TEST_ID1_IDX VALID
SQL> select table_name, tablespace_name
2 from dba_tables
3 where owner = 'TEST';
TABLE_NAME TABLESPACE_NAME
------------------------------ ------------------------------
PLAN_TABLE DEL
TEST DEL
아래의 명령어에서
해당 테이블을 그 자리에 ‘들었다 놓았다’ 이 동작은 사용공간을
최적화 하는 효과가 있다.
SQL> alter table test.test move tablespace del;
Table altered.
아래의 쿼리에선
위에서 참조되는 대상이었던 테이블에 DDL 이 일어나면서 이를 참조하던 TEST_ID1_IDX 가 INVALID 상태가 되었다. 이를 다시
사용하기 위해서는 REBUILD 가 필요하다.
SQL> select index_name,status
2 from dba_indexes
3 where index_name = 'TEST_ID1_IDX';
INDEX_NAME STATUS
------------------------------ --------
TEST_ID1_IDX UNUSABLE
아래의 쿼리에서
REBUILD 하였다.
SQL> alter index test_id1_idx rebuild;
SQL> select index_name,status
2 from dba_indexes
3 where index_name = 'TEST_ID1_IDX';
INDEX_NAME STATUS
------------------------------ --------
TEST_ID1_IDX VALID
아래의 쿼리에선
저장공간을 최적화 하면서 오히려 악화되었다. 이 값이 의미하는 것은 해당 INDEX( SORT 된 상태 )의
ROWID 를 따라갈 때 블록을 여기저기서 들춰본다는 것이다. ( 비효율 )
SQL> @clust
INDEX_NAME CLUSTERING_FACTOR
------------------------------ -----------------
TEST_ID1_IDX 61028
3.
개선안
A. SELECT를 이용한 방법
SQL> conn test/test
Connected.
SQL> select count(*) from test;
COUNT(*)
----------
100000
값을 정렬해서
테이블을 만들었다.
SQL> create table test2
2 as select * from test
3 order by 1 asc;
Table created.
SQL> commit;
Commit complete.
SQL> create index test2_id1_idx on test2(id1);
Index created.
SQL> conn /as sysdba
Connected.
아래의 쿼리에서
통계정보를 수집하였다.
이 과정없이 clustering_factor 를 조회하면 값이 비어있다. ( 인덱스
갓 생성시 )
SQL> analyze index test.test2_id1_idx compute statistics;
Index analyzed.
from 절의 인덱스를 새로만든 이름으로
수정하였다.
SQL> ed clust
SQL> @clust
INDEX_NAME CLUSTERING_FACTOR
------------------------------ -----------------
TEST2_ID1_IDX 975
move tablespace 로 급상한 clustering factor와 달리 ordered 된 값을 가지고 테이블을 만든 경우 위와 같은 값을 얻었다.
위와 같은 방법을 사용해도 여전히 실제 사용 블록수와는 상당한 차이가 있다.
/*+ 방법을 더 찾아보자 !! */