5. 클러스터링 팩터

조회 수 9114 추천 수 0 2010.01.27 21:47:30
balto *.204.128.206

CHAPTER 5. 클러스터링 팩터


발표/총정리 - 박우창

기준 예제 110

/ 박우창

? 클러스터링 팩터를 실험하는 기준이되는 예제 실험 - (base_line.sql)

테이블구조 t1 - 총 26,000개 튜플

(pctfree 90, pctused 10, 8KB 블록사이즈, 1MB 유니폼엑스텐트를 가진 LMT)

열이름

값 list

분포 ( 전체 10,000개)

선택도

date_ord

26개의 날자

각각 약 1000개씩

1/26

seq_ord

1..26000

sequence

1/26000

small_vc

{a,b,c,d,e}*{1..200}

26day에 대하여 생성

1/26

 

 

- 테이블 생성 프로그램 설명

  5개의 세션이 0.01초간 테이블에 lock을 걸고 풀면서 데이터를 생성한다. 각 프로세스가 200개씩 데이터를 load하고 sleep

create or replace procedure t1_load(i_tag varchar2) as

  m_date date;

  begin

  for i in 0..25 loop -- 26 days

    m_date := trunc(sysdate) + i;

      for j in 1..200 loop -- 200 rows per day

        insert into t1 values(

          m_date,

          t1_seq.nextval,

          i_tag || j -- used to identify sessions

        );

        commit;

        dbms_lock.sleep(0.01); -- reduce contention

      end loop;

    end loop;

end;

- 각 세션 (a,b,c,d,e)는 (예를 들면) 다음과 같은 데이터를 생성한다.

ROWID

DATE_ORD

SEQ_ORD

SMALL_VC

AAAMJHAAJAAAAAKAAA

18-FEB-04

1

A1

AAAMJHAAJAAAAAKAAB

18-FEB-04

2

B1

AAAMJHAAJAAAAAKAAC

18-FEB-04

3

C1

AAAMJHAAJAAAAAKAAD

18-FEB-04

4

A2

AAAMJHAAJAAAAAKAAE

18-FEB-04

5

D1

AAAMJHAAJAAAAAKAAF

18-FEB-04

6

E1

AAAMJHAAJAAAAAKAAG

18-FEB-04

7

B2

AAAMJHAAJAAAAAKAAH

18-FEB-04

8

D2

AAAMJHAAJAAAAAKAAI

18-FEB-04

9

B3

AAAMJHAAJAAAAAKAAJ

18-FEB-04

10

E2

 - 생성결과에 대한 설명

(1) 데이터 삽입시 충돌

      CT : 블록 x에서 충돌한 프로세스의 개수(266의 경우 2개의 프로세스가 충돌한 블럭이 266개임)

      COUNT(*) : CT 개의 프로세스가 충돌한 블록의 개수

CT COUNT(*)

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

1          248

2         266

5         39

4         117

3         54

(2) 인덱스 및 클러스터링 팩터 (실험결과 책보다 큰 값의 클러스터링 팩터가 나옴, 교재에서는 1008)

INDEX_NAME BLEVEL LEAF_BLOCKS CLUSTERING_FACTOR

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

T1_I1                   1                         86                                               13090

(3) 예제 질의 결과 : 실험 예의 경우 클러스터링 팩터가 높아서 full scan, 교재에서는 index range scan

Execution Plan(26000개중 1000개 결과 반환)

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

| Id | Operation                     | Name | Rows | Bytes | Cost |

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

| 0  | SELECT STATEMENT    | | 1 | 13                         | 74 |            

| 1  | SORT AGGREGATE | | 1 | 13                                   | |

|* 2 | TABLE ACCESS FULL| T1 | 1000 | 13000               | 74 |

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

(4) 교재 결과의 인덱스 비용 계산(교재와 같이 생성될 경우)

cost =blevel +

          ceil(effective index selectivity * leaf_blocks) +

          ceil(effective table selectivity * clustering_factor)

cost =1 +

          ceil(0.03846 * 86) +

          ceil(0.03846 * 1,008)

       = 1 + 4 + 39 = 44

테이블 경합 줄이기(다중 freelist) 113 /위충환
 

select
    /*+ full(t1) */

    rowid, date_ord, seq_ord, small_vc

from

    t1

where
    rownum <= 10
;

ROWID              DATE_ORD     SEQ_ORD SMALL_VC
------------------ --------- ---------- ----------
AAAMJHAAJAAAAAKAAA 18-FEB-04          1 A1
AAAMJHAAJAAAAAKAAB 18-FEB-04          2 B1
AAAMJHAAJAAAAAKAAC 18-FEB-04          3 C1
AAAMJHAAJAAAAAKAAD 18-FEB-04          4 A2
AAAMJHAAJAAAAAKAAE 18-FEB-04          5 D1
AAAMJHAAJAAAAAKAAF 18-FEB-04          6 E1
AAAMJHAAJAAAAAKAAG 18-FEB-04          7 B2
AAAMJHAAJAAAAAKAAH 18-FEB-04          8 D2
AAAMJHAAJAAAAAKAAI 18-FEB-04          9 B3
AAAMJHAAJAAAAAKAAJ 18-FEB-04         10 E2


  확장 Rowid 구성

  object_id            처음 6개 문자    (AAAMJH)

  상대 file_id         다음 3개 문자    (AAAJ)

  파일 내 블록 번호    다음 6개 문자    (AAAAAK)

  블록 내 로우 위치    마지막 3개 문자  (AAA, AAB, AAC ...)

    small_vc : 프로세스 식별값

 

        문제점

동시성이 높은 시스템에서, 모든 데이터가 하나의 블록에 집중적으로 접근할 경우 해당 블록에서 다수의 buffer busy waits 발생 가능

해결방법 (Oracle Performance Tuning Guide and Reference 인용)

테이블 생성시 FREELIST사용


storage (freelists 5)

오라클 테이블의 세그먼트 헤더 블록의 다섯 개의 FREE 블록 연결 리스트 관리

로우 삽입 시, 프로세스 ID를 사용하여 FREE 블록을 찾기 위한 리스트 결정

5개의 프로세스의 충돌이 없을 수 있음 (100%는 아님) - 완전히 다른 5개 테이블 블록 사용 가능

  •      FREELIST를 5 설정 후 테스트(CF=26000, cost=115, 앞에서는 cost=44)
  • INDEX_NAME               BLEVEL LEAF_BLOCKS CLUSTERING_FACTOR
    -------------------- ---------- ----------- -----------------

    T1_I1                         1          86               26000 


    select count(small_vc)

    from t1
    where date_ord = trunc(sysdate) + 7
    ;


    Execution Plan (9.2.0.6 autotrace)
    ----------------------------------------------------------
    0   SELECT STATEMENT Optimizer=ALL_ROWS (Cost=115 Card=1 Bytes=13)
    1   0 SORT (AGGREGATE)
    2   1 TABLE ACCESS (FULL) OF 'T1' (Cost=115 Card=1000 Bytes=13000)


    클러스터링 팩터 증가

    •  약 1,000 (테이블 블록 개수와 유사) => 26,000(테이블 로우 개수)

    옵티마이저의 처리

    • 하루치 조회 쿼리에서도 인덱스 사용 거부

    • 실제로 하루 입력 데이터는 FREELIST 1일 때와 동일하게 30~35 테이블 블록에 존재로, 단지 로우의 순서만 변경 됨

     

    • FREELIST를 2로 설정 후 오라클이 FREELIST에 블록 추가 시 한 번에 두 개씩만 추가 할 경우

    clustering.jpg

    - 두 프로세스가 완변히 차례로 진행 시 일련번호가 교대로 다른 블록에 나타남

    ∵ 오라클이 클러스터링 팩터 산출 시, 인덱스를 스캔하면서 두 개의 테이블 블록을 번갈아 가리키기 때문에 계속 증가


    - 1~10까지 모든 값을 얻는 데 2개의 블록(1,3 블록)만 읽으면 되지만 오라클의 클러스터링 팩터 계산법은 옵티마이저가 10개의 다른 블록을 방문해야 하는 것으로 착각

    ∵ 최근 이력을 유지하지 않고, 단순히 현재 블록이 이전 블록 같은지 여부만 확인


    leaf 블록 경합 줄이기(reverse key 인덱스) 117

    /이태경

    REVERSE KEY 인덱스

    • 인덱스 구성 컬럼의 순서는 그대로 유지하면서 각 컬럼의 데이터를 바이트 단위의 역순으로 인덱싱하는 것.(이를 통해 인덱스 엔트리를 더 균등하게 분산시킨다.)

    select
    dump(date_ord,16) date_dump,
    dump(seq_no,16) seq_dump
    from t1
    where date_ord = to_date('18-feb-2004')
    and seq_no = 39
    ;
    DATE_DUMP SEQ_DUMP
    ------------------------------ ------------------
    Typ=12 Len=7: 78,68,2,12,1,1,1 Typ=2 Len=2: c1,28

    select
    dump(reverse(date_ord),16) date_dump,
    dump(reverse(seq_no),16) seq_dump
    from t1
    where date_ord = to_date('18-feb-2004')
    and seq_no = 39
    ;
    DATE_DUMP SEQ_DUMP
    ------------------------------ ------------------
    Typ=12 Len=7: 1,1,1,12,2,68,78 Typ=2 Len=2: 28,c1

    REVERSED_SEQ_ORD SEQ_ORD
    28,7,c2 639
    28,8,c2 739
    28,9,c2 839
    28,a,c2 939
    28,c1 39
    29,2,c2 140
    29,3,c2 240
    29,4,c2 340
    29,5,c2 440
    29,6,c2 540

     
    alter index t1_i1 rebuild reverse;
    begin
    dbms_stats.gather_table_stats(
    user,
    't1',
    cascade => true,
    estimate_percent => null,
    method_opt => 'for all columns size 1'
    );
    end;
    /

    INDEX_NAME            BLEVEL  LEAF_BLOCKS  CLUSTERING_FACTOR
    -------------------- --------- -------------- --------------------
    T1_I1                              1                86                25962

    select count(small_vc)
    from t1
    where date_ord = trunc(sysdate) + 7
    ;

    Execution Plan (9.2.0.6 autotrace)
    ----------------------------------------------------------
    0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=115 Card=1 Bytes=13)
    1 0 SORT (AGGREGATE)
    2 1 TABLE ACCESS (FULL) OF 'T1' (Cost=115 Card=1000 Bytes=13000)

    reverse 인덱스의 사용목적과 부작용
    • 테이블 엔트리가 연속된 값으로 들어올 때 인덱스 엔트리를 분산시키기 위해 사용
    • 인접한 엔트리에서 가리키는 테이블 엔트리가 흩어짐 → 클러스터링 팩터 증가 → 실행계획에 영향을 줌( index range scan에서 테이블 스캔으로 변경)

    결론
    • 클러스터링 팩터 계산 메커니즘엔 reverse key 인덱스의 영향도가 반영되지 않음.
    • 따라서 데이터 분포가 변하지 않았음에도 오라클은 크게 변했다고 생각.


    테이블 경합 줄이기(ASSM) 120 /남송휘



    create tablespace test_8k_assm
    blocksize 8K
    datafile test_8k_assm.dbf' size 193m reuse
    extent management local
    uniform size 1M
    segment space management auto
    ;



    • ASSM 의 두가지 주요 특징

    • 구조: assm 테이블 스페이스내 각 세그먼트는 각 익스텐트 시작 부분 몇 개 블록을 사용하여 나머지 블록에 대한 맵을 관리
    • 실행시점: 프로세스가 로우를 삽입할때 프로세스 ID에 의해 결정된 공간 맵 블록을 선택 후 공간맵으로부터 데이터 블록을 선택 (assm 은 dba개입 없이 프로세스간 경합을 최소화하도록 동시 수행되는 프로세스가 데이터 삽입시 다른블록을 선택하는것)
    • 동시 로우 생성에 대한 경합을 회피하기 위해서 오라클이 제공하는 기능의 상대적인 이점과 비용을 조사할 필요가 있음


    실험결과 (assm_test.sql)

    10.2.0.1

    테이블 내 블록의 충돌수

    동시PS개수     블록개수(첫실행)  블록개수 (두번째실행)
            CT        COUNT(*)          COUNT(*)
    ----------   ----------          ----------
             1        343                340
             2        200                203
             5         31                  49
             4         42                  27
             3        109                106


        BLOCKS   NUM_ROWS
    ---------- ----------
           754      26000



    INDEX_NAME               BLEVEL LEAF_BLOCKS CLUSTERING_FACTOR
    -------------------- ---------- ----------- -----------------
    T1_I1                         1          86             20191

    T1_I1                         1          86             20531



    Execution Plan
    ----------------------------------------------------------

    -----------------------------------------------------------
    | Id  | Operation          | Name | Rows  | Bytes | Cost  |
    -----------------------------------------------------------
    |   0 | SELECT STATEMENT   |      |     1 |    13 |    74 |
    |   1 |  SORT AGGREGATE    |      |     1 |    13 |       |
    |*  2 |   TABLE ACCESS FULL| T1   |  1000 | 13000 |    74 |
    -----------------------------------------------------------




     

    RAC에서 경합 줄이기(Freelist Groups) 123 /남송휘

    • 다중 freelist의 경합감소
    • free list 가 자신이 최상위 블록을 가짐으로써 로우 생성이 한블록이 아니라 여러 테이블 블록에서 일어남
    • freelist는 자기의 최상위 블록에 대한 포인터를 가지고 사직하여 모든 포인터가 세그먼트 헤더 블록에 존재하기 때문에 경합지점 존재



    freelist group  예

    create table t1(
        date_ord    date        constraint t1_dto_nn    not null,
        seq_ord        number(6)    constraint t1_sqo_nn    not null,
        small_vc    varchar2(10)
    )
    pctfree 90
    pctused 10
    storage (freelists 2 freelist groups 3)
    ;


     


    • 세그먼트 헤더 블록뒤 세그먼트 시작점에서 freelist group당 한개의 블록을 얻고, 각 블록은 인스턴스 ID과 연관되어 독립적인 FREELIST세트를 관리 (세그먼트 헤데에 의한 경합이 제거)
    • 얼마나 큰값을 설정하는가에 따라 freelist group  사용이 큰효과를 나타낼수 있음

     

    • 클러스터링팩터에 부작용 없이 순서기반 컬럼의 인덱스 리프 블록에 대한 경합을 제거하는 방법
    • sequence의 캐시 사이즈를 충분히 크게 설정한다
    •  ex)  create sequence big_seq cache 10000;
    • 테이블의 freelist를 1로 설정하여 인스턴스에서 캐싱하는 인덱스 블록이 filp-flop 효과의 영햔을 받지 않도록한다
      ( 각 인스턴스가 자기의 개별적인 인덱스 구역을 효율적으로 채우기 때문에 리프블록 분할시 50/50분할이 모든인스턴스에서 발생할수 있음
      인덱스 사이즈가 단일 인스턴스 데이터베이스의 것보다 두 배 가까이 커질수 있음)


    • freelist group 재균형잡기(freelists group의 단점)
    • 이슈
    • 대량 데이터 삭제시 단일 프로세스를 사용하면 이삭자로 비위진 블록이 하나의 freelist group에 등록되어 다른 freelist group의 freelist를 통해 자동으로 사용될수 없음
    •  dbms_repair.rebuild_freelists() ; free 블록을 오브젝트의 모든 freelist group에 균등하게 대분배
    • 오브젝트를 재생성하지 않으면 freelist group의 개수를 바꿀 수없음


    인덱스 컬럼 순서 126

    /박우창

    ? (문제) 인덱스 컬럼 순서 결정시 고려야할 사항

    - 4장에서 WHERE <c1> and <c2> and <c3> 의 경우 <c1>이 범위기반 조건일 때 <c2>,<c3>는 유효인덱스 선택도 계산시 무시되어 비용을 너무 높게 계산한다.

    -> 선택도가 낮은 조건을 앞에 둔다.

    ? (문제) 인덱스 컬럼 순서를 바꾸면 클러스터링 팩터를 바꿀수 있다.(col_order.sql)

          테이블구조 t1

    열이름

    값 list

    분포 ( 전체 10,000개)

    선택도

    clustered

    0..99

    각각 약 100개씩

    1/100

    scattered

    0..99

    clustered 각각 100개

    1/100

    small_vc

    1..10,000

    1개씩

    1/10000

    인덱스구조 t1

    create index t1_i1_good on t1(clustered, scattered);

    create index t1_i2_bad on t1(scattered, clustered);

    ? 테이블 저장 결과(전체 292 블록)

    INDEX_NAME BLEVEL LEAF_BLOCKS CLUSTERING_FACTOR

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

    T1_I1_GOOD 1 24 278

    T1_I2_BAD 1 24 10000

    ? (SQL 실험)

    실험 1

    실험 2

    비용 : 4=3+1

    비용 : 9=2+7

    select/*+ index(t1 t1_i1_good) */

    count(small_vc)

    fromt1

    wherescattered = 50

    andclustered between 1 and 5

    select/*+ index(t1 t1_i2_bad) */

    count(small_vc)

    fromt1

    wherescattered =50

    andclustered between 1 and 5

    access("CLUSTERED">=1 AND

    "SCATTERED"=50 AND

    "CLUSTERED"<=5)

    filter("SCATTERED"=50)

    access("SCATTERED"=50 AND

    "CLUSTERED">=1 AND

    "CLUSTERED"<=5)

    cost (t1_i1_good) =

    1 +

    ceil(0.060404 * 24) +

    /* 첫 번째 조건에 대한 유효선택도 */

    ceil(0.00060404 * 278)

    /* 두 번째 조건을 테이블 방문에 사용 */

    = 1 + 2 + 1 = 4

    cost (t1_i2_bad) =

    1 +

    ceil(0.00060404 * 24) +

    /* 유효선택도 */

    ceil(0.00060404 * 10000)

    /* 매우 큰 클러스터링 팩터 */

    = 1 + 1 + 7 = 9

    'scattered = 50'의 선택도, 1 / 100 = 0.01

    'clustered between 1 and 5'의 선택도, (5 ? 1) / ( 99 ? 0 ) + 2/100 = 0.060404

    총 선택도 : 0.01 * 0.060404 = 0.00060404

    - (참고) 힌트가 없으면 실험 1의 실행계획이 사용된다. 옵티마이저는 테이블 블록 방문 횟수만을 계산하기 때문에 최근에 방문한 블록을 다시 방문하는 비용감소를 반영하지 못한다.

    ? (실험결과)

    - 힌트가 없으면 옵티마이저는 실험1을 선택하며, 실험2는 실험1보다 비용이 크다.

    - 실험2는 계산상 비용은 크지만 실제적으로 테이블의 방문 비용은 실험1과 같다.

    - 인덱스 방문 비용은 인덱스 엔트리를 방문하는 CPU 비용으로 큰 차이가 없다(비용 1)

    - 순서만 다르고 같은 컬럼으로 구성된 2개의 인덱스에서 하나를 선택하는 것은 어렵고, 실행계획에서 차이를 가져올 수 있다.


     

    인덱스 컬럼 추가 129

    /박우창

    ? (문제) 인덱스에 컬럼을 추가하면 클러스터링 팩터에 큰 영향을 줄 수 있다.(extra_col.sql)

       테이블구조 t1

    열이름

    값 list

    분포 ( 전체 10,000개)

    선택도

    movement_date

    1..20

    20개의 서로다른 날자

    1/500

    product_id

    random

    1/10000

    qty

    random

    1/10000

    small_vc

    1..10,000

    1개씩

    1/10000

    padding

    'x'

    rpad

    1

        인덱스구조 t1

    create index t1_i1 on t1(movement_date);

    ? 테이블 저장 결과(전체 194 블록)

    INDEX_NAME BLEVEL LEAF_BLOCKS CLUSTERING_FACTOR

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

    T1_I1 1 27 183

    ? (SQL 실험 1)

    실험 1

    인덱스에 컬럼 추가가 권장되는경우

    실험 2

    인덱스에 컬럼 추가로 불리한 경우

    selectsum(qty)

    fromt1

    wheremovement_date =

    trunc(sysdate) + 7

    andproduct_id = 44

    selectproduct_id, max(small_vc)

    fromt1

    wheremovement_date =

    trunc(sysdate) + 7

    group by product_id

    create index t1_i1 on t1(movement_date);

    INDEX_NAME BLEVEL LEAF_BLOCKS CLUSTERING_FACTOR

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

    T1_I1 1 27 183

    인덱스 t1_i1 사용

    filter("PRODUCT_ID"=44)

    access("MOVEMENT_DATE"=TRUNC(SYSDATE@!)+7)

    인덱스 t1_i1 사용

    access("MOVEMENT_DATE"=TRUNC(SYSDATE@!)+7)

    비용 : 2+10=12

    비용 : 2+10+7(정렬비용)=19

    create index t1_i1 on t1(movement_date, product_id); /* 컬럼 추가 */

    INDEX_NAME BLEVEL LEAF_BLOCKS CLUSTERING_FACTOR

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

    T1_I1 1 31 6645

    인덱스 t1_i1 사용

    access("MOVEMENT_DATE"=TRUNC(SYSDATE@!)+7 AND "PRODUCT_ID"=44)

    full table(t1) 사용

    filter("MOVEMENT_DATE"=TRUNC(SYSDATE@!)+7)

    비용 : 1+6=7

    비용 : 29+7=36

    ? (실험결과)

    - 실험 1의 경우 정교한 인덱스를 통하여 질의 비용을 감소시켰다

    - 실험 2의 경우 클러스터링 팩터에 의하여 인덱스 생성 목적이 사라지면 비용을 증가시킨다.

    - 실험 2의 경우 (실제로는 높지 않지만) 클러스터링 팩터를 높여서 데이터위치를 속이며 인덱스대신 테이블 스캔을 택하게 한다.


    통계정보 바로잡기 132

    /이창헌

    sys_op_countchg( ) 테크닉 132

    /
    get_xxx_stats와 set_xxx_stats의 패키지 함수를 이용해서 클러스터링 팩터를 언제든지 수정 가능

     dbms_stats.get_index_stats(
      ownname  => NULL, 
      indname  => '&m_source_index.',
      numrows  => m_numrows,
      numlblks => m_numlblks,
      numdist  => m_numdist,
      avglblk  => m_avglblk,
      avgdblk  => m_avgdblk,
    --  clstfct  => m_clstfct,
      indlevel => m_indlevel
      indlevel => m_indlevel,
      quessq  => m_guessq
     );

     mm_clstfct = 사용자 정의값
     

     dbms_stats.set_index_stats(
      ownname  => NULL, 
      indname  => '&m_target_index.',
      numrows  => m_numrows,
      numlblks => m_numlblks,
      numdist  => m_numdist,
      avglblk  => m_avglblk,
      avgdblk  => m_avgdblk,
      clstfct  => m_clstfct,
      indlevel => m_indlevel,
      quessq  => m_guessq
     );

     

     

    select /*+
          cursor_sharing_exact
          dynamic_sampling(0)
          no_monitoring
          no_expand
          index(t,"T1_I1")
          noparallel_index(t,"T1_I1")
       */

        sys_op_countchg(substrb(t.rowid,1,15),5) as clf <=클러스터링 팩터값 5의 의미 freelists테스트 블록개수와 비슷한값
    from
        "TEST_USER"."T1"  t
    where
           "DATE_ORD" is not null
        or "SEQ_ORD" is not null
    ;

    5을 인수로 전달 후 리턴값이 너무 큰 값이었던 클러스터링 팩터가 갑자기 매우 적절한 값으로 바꿤

    freelists테스트 블록개수와 비슷한값


    비공식 전략 138

    /박우창

    ? 복합인덱스 컬럼과 클러스터링 사례들

    - reverse key의 사용 : 예제의 (date_ord, seq_no) 경우 같이 선행 컬럼 date_ord가 결정적이며 seq_no는 질의의 정확성에 도움이 되지 않는다.

    - 인덱스 컬럼 추가 : 예제의 (date_movement, product_id) 경우 같이 선행 컬럼 date_movement가 결정적이며 product_id는 작은 역할을 한다.

    - 인덱스 컬럼 재배열 : 예제의 (clustered, scattered) 경우 같이 선행 컬럼 clustered가 테이블의 저장 순서를 결정한다.

    ? 복합인덱스를 포기하고 단일 인덱스를 만들어 클러스터링 팩터를 계산하고 그 결과를 인덱스에 전달하여 적절한 CF를 찾으면 어떻게 되는가?

    -> 2가지는 가능하지만 세 번째는 인덱스 실제 사용과 질의의 특성에 따라 타당성이 달라진다. 

    ? 드라이빙 컬럼에 대한 주장이 실패하면 sys_op_countchg() 테크닉을 사용할 수 있다.

    -> 예제에서 clustered 컬럼에 대하여 9 혹은 10개의 블록의 그룹이 모여있다면 9의 값으로 sys_op_countchg()를 호출한다.

    -> 정답만을 알아내려면 5개의 데이터 블록에 데이터가 존재하고 오라클이 100개의 블록을 방문한다면 클러스터링팩터/20으로 오라클에 알려준다.

    -> 오라클은 방문 테이블 예상치를 user_indexes.avg_data_blocks_per_key를 사용한다

    (= clustering_factor/distinct_keys)

     

    끝으로 139

    /박우창

     

    요약 139

    /박우창

     

    테스트 스크립트 140

    /박우창