2. 1.3 DBMS_STATS 패키지 사용하기
Optimizer Statistics(옵티마이저 통계)는 데이터베이스 모든 오브젝트에 대한 자료를 모아 기술한 통계인데 데이터 딕셔너리(Data
Dictionary)에 저장되며 이 통계정보를 바탕으로 오라클 옵티마이저는 SQL문장 실행을 위한 효율적인 실행계획을 만들어 낸다.
오라클은 테이블이나 인덱스와 같은 데이터베이스 오브젝트에 대한 통계 정보 생성, 삭제, 익스포, 임포트를 용이하게 하기 위해
DBMS_STATS 패키지를 제공하는데 이 패키지를 이용하면 테이블이나 인덱스의 모든 데이터를 근간으로 통계 정보를 생성할 수 있다.
대용량의 테이블이라면 모든 데이터를 가지고 액세스 경로를 추측하는 것보다 샘플링 데이터를 가지고 추측하는 것이 훨씬 용이하다.
대체로 샘플링 데이터는 5% 이하로 ROW나 BLOCK에 만들며 DBMS_STATS 패키지의 automatic sampling 프러시저를 이용하면 된다.
통계정보 수집용 테이블 생성은 DBMS_STATS 패키지의 create_stat_table 프러시저를 이용하여 만들면 된다.
DBMS_STATS 패키지에는 몇 개의 유용한 프러시저가 있는데 아래와 같다.
gather_database_ stats: 데이터베이스의 모든 Object에 대한 통계 정보 생성.
gather_schema_ stats: 해당 스키마의 모든 Object에 대한 통계 정보 생성.
gather_table_stats : 테이블과 그 테이블과 연관된 인덱스에 대한 통계 정보 생성.
gather_index_stats : 인덱스에 대해 통계 정보를 생성.
3. 여기에서 사용된 인자는 접속한 계정, 통계정보 수
집용 테이블 이름, 테이블스페이스 이름이다.
SQL> execute dbms_stats.create_stat_table(USER,
'stat_tab', 'users');
PL/SQL 처리가 정상적으로 완료되었습니다.
-- 아래는 현재 로그온한 스키마 계정과 EMP라는 테
이블에 대해 통계 정보를 생성했다.
SQL> execute
dbms_stats.gather_schema_stats(ownname => USER);
PL/SQL 처리가 정상적으로 완료되었습니다.
SQL> execute
dbms_stats.gather_table_stats(USER,'emp');
PL/SQL 처리가 정상적으로 완료되었습니다.
-- 데이터 딕셔너리에서 생성된 통계정보 확인,
LAST_ANALYZED 칼럼을 확인하라
SQL>SELECT * FROM USER_TABLES WHERE
TABLE_NAME = ‘EMP’;
--테이블 내의 인덱스된 컬럼 들 및 대상 테이블과
연관된 모든 인덱스에 대한 통계 정보 생성
SQL> begin
dbms_stats.gather_table_stats(
USER, 'myemp1',
method_opt =>'for all indexed columns',
cascade => true);
end;
/
-- 생성된 테이블 통계정보 확인
SQL> SELECT NUM_ROWS, BLOCKS, EMPTY_BLOCKS,
AVG_ROW_LEN FROM USER_TAB_STATISTICS
WHERE TABLE_NAME = 'MYEMP1';
NUM_ROWS BLOCKS EMPTY_BLOCKS
AVG_ROW_LEN
-------------------------------------------------------------------
10000002 92328 472 82
-- 생성된 칼럼 통계정보 확인
SQL> SELECT COLUMN_NAME, NUM_DISTINCT,
NUM_NULLS
FROM USER_TAB_COL_STATISTICS
WHERE TABLE_NAME = 'MYEMP1';
COLUMN_NAME NUM_DISTINCT NUM_NULLS
----------------------------------------------------------------------
EMPNO 10000002 0
ENAME 10000002 0
DEPTNO 4 0
ADDR 10000002 0
SAL 6039040 0
JOB 6 0
COMM 989888 8333335
SUNGBYUL 2 0
HIREDATE 1745792 0
OUTDATE 1 8333335
MGR 6 2499998
11 개의 행이 선택되었습니다.
4. 위 예문의 경우 자동으로 테이블과 인덱스의 모든 데이터에 대해 통계 정보가 계산된다. 만약 만들 통계
정보가 단순히 샘플이거나 큰 테이블의 모든 데이터가 아니라 일부의 레코드에 대해 제한하는 경우에는
dbms_stats.auto_sample_size를 이용하면 된다.
-- 현재 MYEMP1 테이블의 통계정보를 STAT_TAB으로 EXPORT
/*
DBMS_STATS.EXPORT_TABLE_STATS (
ownname VARCHAR2,
tabname VARCHAR2,
partname VARCHAR2 DEFAULT NULL, -- 파티션 이름
stattab VARCHAR2, -- 통계정보를 저장하기 위한 통계정보 테이블
statid VARCHAR2 DEFAULT NULL,
cascade BOOLEAN DEFAULT TRUE, -- 인덱스 통계정보도 같이 임포트 할지의 여부
statown VARCHAR2 DEFAULT NULL -- stat table schema name
);
*/
SQL> execute dbms_stats.export_table_stats (USER, 'myemp1',null,'stat_tab');
PL/SQL 처리가 정상적으로 완료되었습니다.
-- 딕셔너리와 STAT_TAB의 통계정보의 차이를 비교, 현재는 차이가 없다.
SQL> select * from table(dbms_stats.diff_table_stats_in_stattab(USER,'myemp1','stat_tab'));
REPORT MAXDIFFPCT
-------------------------------------------------------------------------------- ----------
################################################### 0
-- 통계정보 수집용 테이블 삭제
SQL> execute dbms_stats.drop_stat_table(USER,'stat_tab');
PL/SQL 처리가 정상적으로 완료되었습니다.
5. SQL> execute dbms_stats.gather_schema_stats(ownname => USER, estimate_percen => dbms_stats.auto_sample_size);
PL/SQL 처리가 정상적으로 완료되었습니다.
Oracle 11g에서 DBMS_STATS.AUTO_SAMPLE_SIZE의 작동형태는 다음 URL에서 참조
https://blogs.oracle.com/optimizer/entry/how_does_auto_sample_size
이번에는 시스템과 관련된 통계 정보를 생성해 보자.
DBMS_STATS를 이용하여 CBO(cost based optimizer)에게 system performance 통계정보를 제공 할 수 있는데 이 패키지는
CPU 사용과 I/O 퍼센트 등의 정보를 통계정보 생성시 추가한다. dbms_stats.gather_system_stats 프러시저를 이용하고 파
라미터는 다음과 같다.
Gathering_mode : 통계 정보에 대한 수집을 특정한 시기 또는 기간에 하는 경우에는 interval 이나 start/stop 값을 주면 되
고 noworkload라고 하면 시스템은 통계 정보를 general하게 수집한다.
Interval : Gathering_mode에서 interval이라고 한 경우에만 사용한다.
Stattab : 시스템의 통계 정보가 모아질 테이블을 기술한다.
Statown : 시스템의 통계 정보가 모아질 테이블의 Owner를 기술한다. (현재 패키지를 실행 할 Schema와 다를 경우에 기술)
6. DBMS_STATS.gather_system_stats를 사용하기 전에 job_queue_processes 매개변수를 SET 시켜야 하는데 기본값은 0, 양수
값으로 세팅해야 한다. 그렇지 않으면 gather_system_stats 프러시져가 동작하지 않을 수 있다. 현재 세션에서 이 값을 다
이나믹하게 설정하려면 alter system set job_queue_processes = 20 이라고 하면 된다.
SQL> begin
dbms_stats.gather_system_stats (
gathering_mode => 'interval',
interval => 60, //분단위
stattab => 'stat_tab',
statown => USER);
end;
/
PL/SQL 처리가 정상적으로 완료되었습니다.