04 통계정보I

실행계획 수립시 CBO는 SQL 문장에서 액세스할 데이터 특성을 고려하기 위해 통계 정보를 이용한다.

옵티마이저가 참조하는 통계 정보(4가지)

  • 테이블 통계
  • 인덱스 통계
  • 컬럼 통계(히스토그램 포함)
  • 시스템 통계

(1) 테이블 통계

analyze table emp compute statistics for TABELE ;
analyze table emp estimate statistics sample 5000 rows for TABLE ;
anlayze table emp estimate statistics sample 50 percent for TABLE ;

begin
dbms_stats.gather_table_stats('scott', 'emp', cascade=>false, methode_opt=>'for columns') ;
end ;
/

SELECT num_rows ,
blocks ,
empty_blocks ,
avg_space ,
avg_row_len ,
avg_space_freelist_blocks ,
num_freelist_blocks ,
sample_size ,
last_analyzed
FROM dba_tables
WHERE owner = 'SCOTT'
AND table_name = 'EMP'
















---
NUM_ROWS : 14
BLOCKS : 5
EMPTY_BLOCKS : 0
AVG_SPACE : 0
AVG_ROW_LEN : 37
AVG_SPACE_FREELIST_BLOCKS : 0
NUM_FREELIST_BLOCKS : 0
SAMPLE_SIZE : 14
LAST_ANALYZED : 2010-04-14 오후 10:00:17















---

(2) 인덱스 통계

analyze INDEX emp_pk compute statistics ;

analyze table emp compute statistics for ALL INDEXS ;

analyze table emp compute statistics for TABLE for ALL INDEXS ;

-- 특정 인덱스 통계만 수집
begin
dbms_stats.gather_index_stats (ownname => 'scott', indname => 'emp_pk');
end;
/

  • 테이블에 속한 모든 인덱스 통계도 같이 수집
    begin
    dbms_stats.gather_table_stats ('scoot', 'emp', cascade=>true);
    end;
    /

SELECT blevel ,
leaf_blocks ,
clustering_factor ,
num_rows ,
distinct_keys ,
avg_leaf_blocks_per_key ,
avg_data_blocks_per_key ,
sample_size ,
last_analyzed
FROM dba_indexes
WHERE owner = 'SCOTT'
AND table_name = 'EMP'
AND index_name = 'PK_EMP' ;
















---
BLEVEL : 0
LEAF_BLOCKS : 1
CLUSTERING_FACTOR : 1
NUM_ROWS : 14
DISTINCT_KEYS : 14
AVG_LEAF_BLOCKS_PER_KEY : 1
AVG_DATA_BLOCKS_PER_KEY : 1
SAMPLE_SIZE : 14
LAST_ANALYZED : 2010-04-14 오후 10:00:17















---

create index emp_ename_idx on emp(ename) COMPUTE STATISTICS ;

alter index emp_ename_idx rebuild COMPUTE STATISTICS ;

10g 부터는 이 옵션을 명시하시하지 않다도 자동으로 인텍스 통계까지 수집
=> 이 기능을 방지를 위해서는 _optimizer_compute_index_stats를 flase로 설정

(3) 컬럼 통계

analyze table emp compute statistics for ALL COLUMNS SIZE 254 ;

analyze table emp compute statistics for COLUMNS ENAME SIZE 10, SAL SIZE 20 ;

analyze table emp compute statistics for COLUMNS SIZE 20 ENAME, SAL, HIREDATE ;

analyze table emp compute statistics
for table
for all indexes
for all indexed columns size 254 ;

-- 컬럼 통계 조회
SELECT num_distinct ,
low_value ,
high_value ,
density ,
num_nulls ,
num_buckets ,
last_analyzed ,
sample_size ,
avg_col_len ,
histogram
FROM dba_tab_columns
WHERE owner = 'SCOTT'
AND table_name = 'EMP'
AND column_name = 'DEPTNO' ;
















---
num_distinct : 3
low_value : C10B
HIGH_VALUE : C11F
DENSITY :0.0357142857142857
NUM_NULLS : 0
NUM_BUCKETS : 3
LAST_ANALYZED : 2010-04-14 오후 10:00:17
SAMPLE_SIZE : 14
AVG_COL_LEN : 2
HISTOGRAM : FREQUENCY















---

-- 컬럼 히스토그램 조회
SELECT endpoint_value ,
endpoint_number
FROM dba_histograms
WHERE owner = 'SCOTT'
AND table_name = 'EMP'
AND column_name = 'DEPTNO'
ORDER BY endpoint_value ;

ENDPOINT_VALUE ENDPOINT_NUMBER




--


---
10 3
20 8
30 14

(4) 시스템 통계

시스템 통계는 I/O, CPU 성능과 같은 하드웨어 특성을 측정한 것
+ CPU 속도
+ 평균적인 Single Block I/O 속도
+ 평균적인 Multiblock I/O 속도
+ 평균적인 Multiblock I/O 개수
+ I/O 서브시스템의 최대 처리량(Throughput)
+ 병렬 Slave의 평균적인 처리량(Throughput)

SELECT sname ,
pname ,
pval1 ,
pval2
FROM sys.aux_stats$ ;

Workload 시스템 통계

spuspeed 현재 시스템에서 단일 CPU가 초당 수행할 수 있는 표준 오퍼레이션 개수(단위 : 백만/초)
sreadtim 평균적인 Single Block I/O 속도(단위 : ms = 1/1000초)
mreadtim 평균적인 Multi Block I/O 속도(단위 : ms = 1/1000초)
mbrc Multi Block I/O 방식을 사용할 때 평균적으로 읽은 블록 수
maxthr I/O 서버시스템의 최대 처리량(단위 : 바이트/초)
slavethr 병렬 Slave의 평균적인 처리량(eksdnl : 바이트/초)

  • 단일 CPU로 초당 백만 개의 표준 오퍼레이션을 수행할 수 있다.
  • Single Block I/O 속도는 평균적으로 ms 이다.
  • Multi Block I/O 속도는 평균적으로 ms 이다.
  • Multi Block I/O 방식을 사용할 때 평균적으로 개 블록 씩 읽는다.
  • I/O 서브시스템으로부터 초당 최대 GB를 읽을 수 있다.
  • 평균적으로 병렬 Slave가 초당 MB를 읽는다.

1. 시스템 통계를 담을 테이블(mystats)를 생성

begin
dbms_stats.create_stat_table(
ownname => USER,
stattab => 'mystats',
tblspace => 'USERS',
global_temporary => FALSE
);
end;
/

2. 시스템 통계를 수집

<방법1>
begin
dbms_stats.gather_system_stats(
gathering_mode => 'interval',
interval => 720,
stattab => 'mystats',
statid => 'OLTP'
);
end;
/

<방법2>
begin
dbms_stats.gather_system_stats(
gathering_mode => 'start',
stattab => 'mystats',
statid => 'OLTP'
);
end;
/

begin
dbms_stats.gather_system_stats(
gathering_mode => 'stop',
stattab => 'mystats',
statid => 'OLTP'
);
end;
/

운영중인 시스템 통계를 mystats에 저장하려면 아래 명령어 사용

begin
dbms_stats.export_system_stats('mystats', 'OLTP', 'USER);
end;
/

3. OS 상에서 Exp/Imp 명령러를 이용해 통계 테이블(mystats)을 테스트 서버로 복제

4. 복제한 통계 데이터를 테스트 서버에 적용

begin
dbms_stats.import_system_stats('mystats', 'OLTP', 'USER);
end;
/

만약 운영 서버에 수집된 값을 수정으로 설정하려면 아래와 같이 수행

begine
dbms_stats.set_system_stats('CPUSPEED', 500);
dbms_stats.set_system_stats('SREADTIM', 5.0);
dbms_stats.set_system_stats('MREADTIM', 30.0);
dbms_stats.set_system_stats('MBRC', 12);
end;
/

5. 시스템 통게를 적용하더라도 캐싱되어 있는 실행계획에는 영향을 미치지 않으로 Shared Pool Flush

alter system flush shared_pool ;

NoWorkload 시스템 통계

cpuspeednw

ioseektim

iotfrspeed

  • cpuspeed = cpuspeednw
  • mbrc = db_file_multiblock_read_count
  • sreadtim = ioseektim + db_block_size / iotfrspeed
  • mreadtim = ioseektim + mbrc * db_block_size / iotfrspeed

NoWorkload 시스템 통계 수집시는 아래와 같이 수행
begin
dbms_stats.gather_system_stats(gathering_mode = > 'NOWORKLEAD');
end;
/