Data Base/SQL 튜닝

통계 수집

잇꼬 2024. 2. 26. 09:16
728x90
반응형
SMALL

#1) 테이블 통계

analyze table employees compute statistics for table;


#2) 컬럼 통계 (단, 함부러 수행 하지 않는다.)

analyze table employees compute statistics for all columns size 254;
analyze table employees compute statistics for columns job_id size 20, department_id size 10;


#3) 인덱스 통계

analyze index emp_emp_id_pk compute statistics;


#) 통계 수집 -> 라이브러리 캐시 -> 실행계획(hard parsing) 생성-> latch 잡기 -> 겹합 발생 -> 대기발생
#1) 개별_index

exec dbms_stats.gather_index_stats('HR', 'emp_emp_id_pk')


#2) table

1) cascade => true : 테이블 통계 수집하면서 관련 있는 인덱스 통계 수집도 함께 수행한다.
2) cascade => false: 테이블 통계 수집하면서 관련 있는 인덱스 통계 수집은 하지 않는다.

exec dbms_stats.gather_table_stats('HR', 'EMP', method_opt=>'for columns size 20 job_id', cascade => true);


#) no_invalidate 옵션

exec dbms_stats.gather_table_stats('HR', 'EMP', method_opt=>'for columns size 20 job_id', cascade => true, no_invalidate => true);

 

no_invalidate: 라이브러리 캐시에 캐싱된 커서를 무효화 할지 결정
no_invalidate => true : 연관된 커서(LCO) 를 무효화 하지 않겠다(10g)
no_invalidate => false : 연관된 커서(LCO) 를 무효화 한다(9i), 경합 발생량 높아짐.
no_invalidate => dbms_stats.auto_invalidate : 정해진 시간동안 조금씩 무효화(10g) 
_optimizer_invalidation_period = 18000(초) (히든 파라미터)

<sys sess>

desc col$
 Name                                                                                Null?    Type
 ----------------------------------------------------------------------------------- -------- --------------------------------------------------------
 OBJ#                                                                                NOT NULL NUMBER
 COL#                                                                                NOT NULL NUMBER
 SEGCOL#                                                                             NOT NULL NUMBER
 SEGCOLLENGTH                                                                        NOT NULL NUMBER
 OFFSET                                                                              NOT NULL NUMBER
 NAME                                                                                NOT NULL VARCHAR2(30)
 TYPE#                                                                               NOT NULL NUMBER
 LENGTH                                                                              NOT NULL NUMBER
 FIXEDSTORAGE                                                                        NOT NULL NUMBER
 PRECISION#                                                                                   NUMBER
 SCALE                                                                                        NUMBER
 NULL$                                                                               NOT NULL NUMBER
 DEFLENGTH                                                                                    NUMBER
 DEFAULT$                                                                                     LONG
 INTCOL#                                                                             NOT NULL NUMBER
 PROPERTY                                                                            NOT NULL NUMBER
 CHARSETID                                                                                    NUMBER
 CHARSETFORM                                                                                  NUMBER
 SPARE1                                                                                       NUMBER
 SPARE2                                                                                       NUMBER
 SPARE3                                                                                       NUMBER
 SPARE4                                                                                       VARCHAR2(1000)
 SPARE5                                                                                       VARCHAR2(1000)
 SPARE6                                                                                       DATE


col$
 OBJ#,  COL#
join
col_usage$
 OBJ#, INTCOL# 

desc col_usage$
Name                                                                                Null?    Type
 ----------------------------------------------------------------------------------- -------- --------------------------------------------------------
 OBJ#                                                                                         NUMBER
 INTCOL#                                                                                      NUMBER
 EQUALITY_PREDS                                                                               NUMBER
 EQUIJOIN_PREDS                                                                               NUMBER
 NONEQUIJOIN_PREDS                                                                            NUMBER
 RANGE_PREDS                                                                                  NUMBER
 LIKE_PREDS                                                                                   NUMBER
 NULL_PREDS                                                                                   NUMBER
 TIMESTAMP                                                                                    DATE


■ optimizer
- 사용자가 요청한 SQL문을 가장 효율적이고 빠르고 수행할 수 있는 최저 비용의 처리 경로를 선택해주는 엔진

1. Rule Based Optimization(RBO)
...


2. Cost Based Optimization(CBO)
- oracle 7 부터 지원. 통계정보를 통해서 생성된다.
- cost 를 기반으로 SQL 최적화 수행.
- 실제 SQL을 수행할 때 소요될 비용을 미리 예측하고 그 값을 기준으로 실행 계획을 설정.
- object 통계 정보
#1) table의 통계

select * from dba_tables;


#2) column의 통계

select * from dba_tab_columns;
desc sys.col$


#3) index의 통계

select * from dba_indexes;


- system 통계 정보
cup 속도, disk I/O 

■ SYSTEM 통계
- 9i 버전 부터 하드웨어 및 애플리케이션 특성에 맞는 시스템 통계를 수집하고 활용
- i/o, cpu 성능 같은 하드웨어 특성
1) cpu 속도
2) 평균적인 single block i/o 속도, multiblock i/o 속도
3) 평균적인 multiblock i/o 갯수
4) i/o 서브 시스템의 최대 처리량(throughput)
5) 병렬 slave 의 평균적 처리량(throughput)

<sys sess>

select * from sys.aux_stats$;
SNAME                PNAME                      PVAL1 PVAL2
-------------------- -------------------- ----------- ------------------------------
SYSSTATS_INFO        STATUS                           COMPLETED
SYSSTATS_INFO        DSTART                           08-25-2013 05:42
SYSSTATS_INFO        DSTOP                            08-25-2013 05:42
SYSSTATS_INFO        FLAGS                          1
SYSSTATS_MAIN        CPUSPEEDNW                  2734
SYSSTATS_MAIN        IOSEEKTIM                     10
SYSSTATS_MAIN        IOTFRSPEED                  4096
SYSSTATS_MAIN        SREADTIM
SYSSTATS_MAIN        MREADTIM
SYSSTATS_MAIN        CPUSPEED
SYSSTATS_MAIN        MBRC
SYSSTATS_MAIN        MAXTHR
SYSSTATS_MAIN        SLAVETHR


□ noworkload 시스템 통계(10g) 
: 명시적으로 시스템 통계 수집을 하지 않더라도 CPU 비용 모델을 사용할 수 있도록 하기 위해서 오라클이 내부적으로 시스템 통계 설정
CPUSPEEDNW: CPU 속도(백만/초)
IOSEEKTIM: 데이터를 읽으려고 디스크 헤드를 옮기는데 걸리는 시간, 보편적(5 ~ 15ms)
IOTFRSPEED : OS 프로세스, i/o 서브 시스템 으로부터 데이터를 읽는 속도(byte/ms)

□ workload 시스템 통계(9i) 
: 실제 애플리케이션에서 발생하는 부하를 측정한 값. 가장 pick한 시간에 체크하는게 좋다
SREADTIM: 평균적 single block i/o 속도(ms=1/1000초)
MREADTIM: 평균적 multi block i/o 속도(ms=1/1000초)
CPUSPEED: 단일 CPU가 초당 수행할 수 있는 오퍼레이션 수(백만/초)
MBRC: multi block i/o 발생시 평균적으로 읽은 블록수
MAXTHR: i/o 서브 시스템의 초당 최대 처리량(byte/초)
SLAVETHR: 병렬 slave의 평균적인 초당 처리량(byte/초)

#) noworkload 시스템 통계 수집
<sys sess>

execute dbms_stats.gather_system_stats(gathering_mode => 'NOWORKLOAD')

 

select * from sys.aux_stats$;
SNAME                PNAME                      PVAL1 PVAL2
-------------------- -------------------- ----------- ------------------------------
SYSSTATS_INFO        STATUS                           COMPLETED
SYSSTATS_INFO        DSTART                           02-23-2024 14:28 -- 변경
SYSSTATS_INFO        DSTOP                            02-23-2024 14:28 -- 변경
SYSSTATS_INFO        FLAGS                          1
SYSSTATS_MAIN        CPUSPEEDNW                  2873
SYSSTATS_MAIN        IOSEEKTIM                     12
SYSSTATS_MAIN        IOTFRSPEED                  4096
SYSSTATS_MAIN        SREADTIM
SYSSTATS_MAIN        MREADTIM
SYSSTATS_MAIN        CPUSPEED
SYSSTATS_MAIN        MBRC
SYSSTATS_MAIN        MAXTHR
SYSSTATS_MAIN        SLAVETHR


#) workload 시스템 통계 수집
#) interval: 분단위로 설정 | 1분동안 수집할거야!

execute dbms_stats.gather_system_stats(gathering_mode => 'interval', interval=>1)



select * from sys.aux_stats$;
SNAME                PNAME                      PVAL1 PVAL2
-------------------- -------------------- ----------- ------------------------------
SYSSTATS_INFO        STATUS                           AUTOGATHERING
SYSSTATS_INFO        DSTART                           02-23-2024 14:30
SYSSTATS_INFO        DSTOP                            02-23-2024 14:31
SYSSTATS_INFO        FLAGS                          0
SYSSTATS_MAIN        CPUSPEEDNW                  2873
SYSSTATS_MAIN        IOSEEKTIM                     12
SYSSTATS_MAIN        IOTFRSPEED                  4096
SYSSTATS_MAIN        SREADTIM
SYSSTATS_MAIN        MREADTIM
SYSSTATS_MAIN        CPUSPEED
SYSSTATS_MAIN        MBRC
SYSSTATS_MAIN        MAXTHR
SYSSTATS_MAIN        SLAVETHR
SYSSTATS_TEMP        SBLKRDS                   197322
SYSSTATS_TEMP        SBLKRDTIM                 419907
SYSSTATS_TEMP        MBLKRDS                     7337
SYSSTATS_TEMP        MBLKRDTIM                  67815
SYSSTATS_TEMP        CPUCYCLES                2628444
SYSSTATS_TEMP        CPUTIM                    916064
SYSSTATS_TEMP        JOB                          521
SYSSTATS_TEMP        CACHE_JOB                    522
SYSSTATS_TEMP        MBRTOTAL                  270614


#) 멈추기

execute dbms_stats.gather_system_stats(gathering_mode => 'start')
execute dbms_stats.gather_system_stats(gathering_mode => 'stop')


※ 테스트(개발) 데이터베이스 시스템 통계 정보를 운영 시스템 통계 정보로 운영
=> 맞춰주는게 제일 좋다! 개발 DB = 운영 DB 

begin
    dbms_stats.set_system_stats('SREADTIM', 1.2);
    dbms_stats.set_system_stats('MREADTIM', 1.3);
    dbms_stats.set_system_stats('MBRC', 16);
    dbms_stats.set_system_stats('CPUSPEED', 700);
    dbms_stats.set_system_stats('MAXTHR', 40580544);
    dbms_stats.set_system_stats('SLAVETHR', 32224);
end;
/


#) optimizer_mode 확인

<sys sess>

show parameter optimizer_mode
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
optimizer_mode                       string      ALL_ROWS

 



■ optimizer_mode 
=> ☆통계정보 중요
1. choose : 통계 정보 => 있으면 all_rows, 없으면 rule (9i 기본값)
2. rule : 통계 정보와 상관없이 RBO 사용
/* CBO 나오고 부터 나온 것 3가지 */
3. all_rows : 전체 처리율의 최적화(10g 기본값), 보편적으로 설정 => 환경: 분석업무, batch성 업무, 의사소통(dss) 업무 => 선호: full table scan 유도
4. first_rows : 최조 응답속도 최적화 => 환경: oltp성 업무 => 선호: index scan 유도
5. first_rows_n(1,10,100,1000) : 처음 결과가 나올때까지의 시간을 줄이기 위해 최적화 => 환경: oltp성 업무 => 선호: index scan 유도

#) optimizer_mode 설정 변경
<sys sess>
-- 함부로 system set 하지 말것! 

alter system set optimizer_mode = first_rows;


#) 파라미터에서 설정, session level에서 진행

alter session set optimizer_mode = first_rows_10;


■ optimizer 에게 영향을 주는 요소 
- 오라클 버전
- 옵티마이저 관련 파라미터: all_rows, first_rows

alter system set optimizer_mode = first_rows; 
alter system set optimizer_mode = all_rows;

- 통계정보 
- 옵티마이저 힌트
- SQL문, 연산자
- 인덱스 설계
- 제약조건: primary key, foreign key

SQL문
parser 처리
 Quert Transformer -> Estimator -> Plan Generator
1. Quert Transformer : SQL 을 최적화 하기 쉬운 형태로 변환
2. Estimator 
- selectivity : 전체 대상 행 중에 특정한 조건에 의해 선택될 것으로 예상되는 row의 수(비율: E-Rows) (1/num_distinct)
- cardinality : 특정 access 단계를 거치고 나서 출력될 것으로 예상되는 결과 건수 (총 로우의 수 * 선택도 = num_rows/num_distinct)
- cost 
1) 특정 명령문을 실행하는데 필요한 표준화된 i/o에 대한 옵티마이저의 최적 '예측비용'
2) _optimizer_cost_model(히든파라미터) = {io|cpu|choose} 
- i/o 비용(8i) : full scan 으로 진행
- cpu 비용(10g) 
- choose 비용: 시스템 통계가 있으면 cpu비용, 없으면 i/o 비용(9i)

3. Plan Generator : 후보군이 될만한 실행계획들을 생성(그 중 저렴한 걸로 리턴)

■ histogram
- 조건절에 자주 사용되는 컬럼들 중에 값의 분포도가 균일하지 않는 컬럼에 히스토그램을 생성한다.
- 버킷의 최대 갯수: 254개
- 히스토그램의 유형
  1) 도수분포 히스토그램(Frequency): 값의 수 = 버킷 갯수
  2) 높이 균형 히스토그램(Height-Balanced): 값의 수 > 버킷 갯수 | 범위 스캔
- method_opt=>'for all columns size 254' : 모든 컬럼에 히스토그램 생성. 단, 주의해서 사용할 것.
- method_opt=>'for columns size 20 job_id: 하나의 컬럼에 히스토그램 생성.
- method_opt=>'for columns job_id size 20, department_id size 12' : 여러 컬럼에 히스토그램을 생성.
- method_opt=>'for columns size 20 job_id, department_id' : 동일한 버킷 갯수로 여러 컬럼에 히스토그램을 생성.
- 버킷갯수 설정
  1) size [integer | repeat| auto | skewonly] : 옵션
  2) integer: 1~254
  3) repeat: 히스토그램이 기존에 생성돼 있던 컬럼에만 히스토그램 수집
    ex) method_opt=>'for all columns size repeat'; 
  4) auto : 컬럼이 조건절에 사용되는 비중이 높은 컬럼(sys.col_usage$, col$)을 찾아 히스토그램 생성. 데이터 분포를 기준으로 자동 결정
    ex) method_opt=>'for all columns size auto'; 
  5) skewonly: 데이터 분포를 분석해 균일하지 않은 컬럼에 대해서 히스토그램 생성.

■ 자동 통계 수집 (10g)

select client_name, status from dba_autotask_client;
CLIENT_NAME                                                      STATUS
---------------------------------------------------------------- --------
auto optimizer stats collection: 무료                             ENABLED
(한번도 gather하지 않은 table)
auto space advisor:비용지불(라이센스 구매용)                       ENABLED
(재구성하는 table 찾아서 권고 해준다 -> 로우마이그레이션 현상 이루어졌을 때의 table, full table scan)
sql tuning advisor:비용지불(라이센스 구매용)                       ENABLED
(oracle이 직접 sql tunuing 해주기)


#) 설정

select client_name, status, consumer_group, window_group from dba_autotask_client;
CLIENT_NAME                         STATUS   CONSUMER_GROUP                 WINDOW_GROUP
----------------------------------- -------- ------------------------------ ------------------------------
★ auto optimizer stats collection     ENABLED  ORA$AUTOTASK_STATS_GROUP       ORA$AT_WGRP_OS ★ 
=> 어느 일정 시간에 작업을 운영하고 있는지 체크
auto space advisor                  ENABLED  ORA$AUTOTASK_SPACE_GROUP       ORA$AT_WGRP_SA
sql tuning advisor                  ENABLED  ORA$AUTOTASK_SQL_GROUP         ORA$AT_WGRP_SQ


#) 요일별로 확인 가능

select * from dba_scheduler_wingroup_members where window_group_name = 'ORA$AT_WGRP_OS';
WINDOW_GROUP_NAME              WINDOW_NAME
------------------------------ ------------------------------
ORA$AT_WGRP_OS                 MONDAY_WINDOW
ORA$AT_WGRP_OS                 TUESDAY_WINDOW
ORA$AT_WGRP_OS                 WEDNESDAY_WINDOW
ORA$AT_WGRP_OS                 THURSDAY_WINDOW
ORA$AT_WGRP_OS                 FRIDAY_WINDOW
ORA$AT_WGRP_OS                 SATURDAY_WINDOW
ORA$AT_WGRP_OS                 SUNDAY_WINDOW


#) 작업량 확인

select window_name, resource_plan, repeat_interval, duration from dba_scheduler_windows;
WINDOW_NAME               RESOURCE_PLAN                       REPEAT_INTERVAL                                              DURATION
------------------------- ----------------------------------- ------------------------------------------------------------ -------------------------
MONDAY_WINDOW             DEFAULT_MAINTENANCE_PLAN            freq=daily;byday=MON;byhour=22;byminute=0; bysecond=0        +000 04:00:00
TUESDAY_WINDOW            DEFAULT_MAINTENANCE_PLAN            freq=daily;byday=TUE;byhour=22;byminute=0; bysecond=0        +000 04:00:00
WEDNESDAY_WINDOW          DEFAULT_MAINTENANCE_PLAN            freq=daily;byday=WED;byhour=22;byminute=0; bysecond=0        +000 04:00:00
THURSDAY_WINDOW           DEFAULT_MAINTENANCE_PLAN            freq=daily;byday=THU;byhour=22;byminute=0; bysecond=0        +000 04:00:00
FRIDAY_WINDOW             DEFAULT_MAINTENANCE_PLAN            freq=daily;byday=FRI;byhour=22;byminute=0; bysecond=0        +000 04:00:00
SATURDAY_WINDOW           DEFAULT_MAINTENANCE_PLAN            freq=daily;byday=SAT;byhour=6;byminute=0; bysecond=0         +000 20:00:00
SUNDAY_WINDOW             DEFAULT_MAINTENANCE_PLAN            freq=daily;byday=SUN;byhour=6;byminute=0; bysecond=0         +000 20:00:00
WEEKNIGHT_WINDOW                                              freq=daily;byday=MON,TUE,WED,THU,FRI;byhour=22;byminute=0; b +000 08:00:00
                                                              ysecond=0
WEEKEND_WINDOW                                                freq=daily;byday=SAT;byhour=0;byminute=0;bysecond=0          +002 00:00:00

9 rows selected.


#) 다음 작업 시간까지 확인 가능

select window_name, window_next_time, autotask_status, optimizer_stats, segment_advisor, sql_tune_advisor
from dba_autotask_window_clients;

 

WINDOW_NAME               WINDOW_NEXT_TIME                                                            AUTOTASK OPTIMIZE SEGMENT_ SQL_TUNE
------------------------- --------------------------------------------------------------------------- -------- -------- -------- --------
MONDAY_WINDOW             26-FEB-24 10.00.00.000000 PM EST5EDT                                        ENABLED  ENABLED  ENABLED  ENABLED
TUESDAY_WINDOW            27-FEB-24 10.00.00.000000 PM EST5EDT                                        ENABLED  ENABLED  ENABLED  ENABLED
WEDNESDAY_WINDOW          28-FEB-24 10.00.00.000000 PM EST5EDT                                        ENABLED  ENABLED  ENABLED  ENABLED
THURSDAY_WINDOW           22-FEB-24 10.00.00.000000 PM EST5EDT                                        ENABLED  ENABLED  ENABLED  ENABLED
FRIDAY_WINDOW             23-FEB-24 10.00.00.000000 PM EST5EDT                                        ENABLED  ENABLED  ENABLED  ENABLED
SATURDAY_WINDOW           24-FEB-24 06.00.00.000000 AM EST5EDT                                        ENABLED  ENABLED  ENABLED  ENABLED
SUNDAY_WINDOW             25-FEB-24 06.00.00.000000 AM EST5EDT                                        ENABLED  ENABLED  ENABLED  ENABLED

 

=> if) batch 프로그램이 돌아가면 cpu가 많이 돌아가고 i/o도 많이 돌아가니 사용되지 않는 시간대로 설정한다.

#) 설정

execute dbms_scheduler.set_attribute('FRIDAY_WINDOW','freq=daily;byday=FRI;byhour=22;byminute=0; bysecond=0');


#) 특정 시간 설정

execute dbms_scheduler.set_attribute(name => 'MONDAY_WINDOW', attribute => 'duartion', value => numtodsinterval(5, 'hour')); --day, hour, minute, second


#) 히스토리 확인

select client_name, job_status, job_start_time, job_duration from dba_autotask_job_history;


# 자동 통계 수집 비활성화

begin 
	dbms_auto_task_admin.disable(client_name => 'auto optimizer stats collection', 
                                 operation => NULL, 
                                 window_name => NULL);
end;
/


#) 비활성화 확인

select client_name, status, consumer_group, window_group from dba_autotask_client;

 

CLIENT_NAME                         STATUS   CONSUMER_GROUP                 WINDOW_GROUP
----------------------------------- -------- ------------------------------ ------------------------------
auto optimizer stats collection     DISABLED ORA$AUTOTASK_STATS_GROUP       ORA$AT_WGRP_OS
auto space advisor                  ENABLED  ORA$AUTOTASK_SPACE_GROUP       ORA$AT_WGRP_SA
sql tuning advisor                  ENABLED  ORA$AUTOTASK_SQL_GROUP         ORA$AT_WGRP_SQ


# 자동 통계 수집 활성화

begin 
	dbms_auto_task_admin.enable(client_name => 'auto optimizer stats collection', 
                                operation => NULL, 
                                window_name => NULL);
end;
/


#) 활성화 되었는지 확인

select client_name, status, consumer_group, window_group from dba_autotask_client;
CLIENT_NAME                         STATUS   CONSUMER_GROUP                 WINDOW_GROUP
----------------------------------- -------- ------------------------------ ------------------------------
auto optimizer stats collection     ENABLED  ORA$AUTOTASK_STATS_GROUP       ORA$AT_WGRP_OS
auto space advisor                  ENABLED  ORA$AUTOTASK_SPACE_GROUP       ORA$AT_WGRP_SA
sql tuning advisor                  ENABLED  ORA$AUTOTASK_SQL_GROUP         ORA$AT_WGRP_SQ


#) 통계 수집 레벨 확인

show parameter statistics_level
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
statistics_level                     string      TYPICAL (기본값)


#) 기본값 변경

alter system set statistics_level = typical;
alter system set statistics_level = all;

  
#) 옵션
statistics_level = [ basic | typical | all ]
- mmon의 역할 : 통계수집을 하는 프로세스

옵션 해석
statistics_level = basic 통계 수집 하지 않겠다. 
statistics_level = typical 기본적인 일부 통계 수집만 하겠다.
statistics_level = all 가능한 모든 통계 수집을 하겠다.



#) optimizer_dynamic_sampling 확인

show parameter optimizer_dynamic_sampling
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
optimizer_dynamic_sampling           integer     2 (1 ~ 10, 기본값을 설정하는 것이 제일 best!)


<sys sess>

drop table hr.emp_new purge;
create table hr.emp_new nologging as select employee_id, last_name, salary from hr.employees;
explain plan for select * from hr.emp_new where employee_id = 100;
select num_rows, blocks, avg_row_len, last_analyzed from dba_tables where table_name = 'EMP_NEW';
  NUM_ROWS     BLOCKS AVG_ROW_LEN LAST_ANAL
---------- ---------- ----------- ---------

explain plan for select * from hr.emp_new where employee_id = 100;

-----------------------------------------------------------------------------
| Id  | Operation         | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |         |     1 |    40 |     3   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| EMP_NEW |     1 |    40 |     3   (0)| 00:00:01 |
-----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("EMPLOYEE_ID"=100)

Note
-----
   - dynamic sampling used for this statement (level=2)



#) 통계 수집

exec dbms_stats.gather_table_stats(ownname =>'hr', tabname => 'emp_new', degree => 2)

 

select num_rows, blocks, avg_row_len, last_analyzed from dba_tables where table_name = 'EMP_NEW';
  NUM_ROWS     BLOCKS AVG_ROW_LEN LAST_ANAL
---------- ---------- ----------- ---------
       107          4          14 23-FEB-24


#) 변경된 정보(들) 확인. 즉, 모니터링 확인.

select * from dba_tab_modifications where table_name = 'EMP_NEW';

=> no rows selected

#) emp_new 에 insert 문 실행

insert into hr.emp_new(employee_id, last_name, salary) values(300, 'oracle', 1000);
insert into hr.emp_new(employee_id, last_name, salary) values(301, 'itwill', 2000);
commit;


#) insert문 이후 변경된 정보(들) 확인.:  smon이 모니터링 함.

select * from dba_tab_modifications where table_name = 'EMP_NEW';

=> no rows selected

#) 모니터링 진행시킴.

해석) smon 일해!

exec dbms_stats.flush_database_monitoring_info

 

select * from dba_tab_modifications where table_name = 'EMP_NEW' and table_owner = 'HR';
TABLE_OWNER TABLE_NAME  PARTITION_NAME  SUBPARTITION_NAME  INSERTS UPDATES DELETES TIMESTAMP TRU DROP_SEGMENTS
----------- ----------- --------------- ------------------ ------- ------- ------- --------- --- -------------
HR          EMP_NEW                                             2        0       0 23-FEB-24 NO              0


#) 위의 쿼리문을 실행했을 경우, 출력이 'no rows selected'으로 나왔을 때

select inserts, updates, deletes, truncated, drop_segments, 
	to_char(timestamp, 'yyyy-mm-dd hh24:mi:ss') timestamp 
from dba_tab_modifications 
where table_name = 'EMP_NEW' and table_owner = 'HR';
  INSERTS    UPDATES    DELETES TRU DROP_SEGMENTS TIMESTAMP
---------- ---------- ---------- --- ------------- -------------------
         2          0          0 NO              0 2024-02-23 16:21:18


#) update문 실행 

update hr.emp_new set salary = salary *1.1 where salary > 10000;
commit;


#) smon 모니터링

exec dbms_stats.flush_database_monitoring_info


select * from dba_tab_modifications where table_name = 'EMP_NEW' and table_owner = 'HR';
TABLE_OWNER TABLE_NAME  PARTITION_NAME  SUBPARTITION_NAME  INSERTS UPDATES DELETES TIMESTAMP TRU DROP_SEGMENTS
----------- ----------- --------------- ------------------ ------- ------- ------- --------- --- -------------
HR          EMP_NEW                                             2       15       0 23-FEB-24 NO              0



#) delete문 실행 

delete from hr.emp_new where employee_id in (100, 101, 102, 103, 104);
commit;

 

exec dbms_stats.flush_database_monitoring_info
select * from dba_tab_modifications where table_name = 'EMP_NEW' and table_owner = 'HR';
TABLE_OWNER TABLE_NAME  PARTITION_NAME  SUBPARTITION_NAME  INSERTS UPDATES DELETES TIMESTAMP TRU DROP_SEGMENTS
----------- ----------- --------------- ------------------ ------- ------- ------- --------- --- -------------
HR          EMP_NEW                                             2       15       5 23-FEB-24 NO              0



select num_rows, last_analyzed, stale_stats from dba_tab_statistics where table_name = 'EMP_NEW';
 NUM_ROWS LAST_ANAL STA
---------- --------- ---
       107 23-FEB-24 YES

stale_stats = YES : 마지막 통계 수집 이후의 10% 이상의 변화율이 관측된 테이블을 의미한다.

#) 모니터링 

exec dbms_stats.gather_table_stats(ownname =>'hr', tabname => 'emp_new', degree => 2)

 

select inserts, updates, deletes, truncated, drop_segments, 
	to_char(timestamp, 'yyyy-mm-dd hh24:mi:ss') timestamp 
from dba_tab_modifications 
where table_name = 'EMP_NEW' and table_owner = 'HR';

=> no rows selected

select num_rows, last_analyzed, stale_stats 
from dba_tab_statistics 
where table_name = 'EMP_NEW';
  NUM_ROWS LAST_ANAL STA
---------- --------- ---
       104 23-FEB-24 NO

 

# stale 상태로 빠지는 변화율의 값을 바꾸는 기능

exec dbms_stats.set_table_prefs('hr', 'emp_new', 'STALE_PERCENT', '40')
select * from dba_tab_stat_prefs;
OWNER                          TABLE_NAME                     PREFERENCE_NAME
------------------------------ ------------------------------ ------------------------------
PREFERENCE_VALUE
--------------------------------------------------------------------------------------------
HR                             EMP_NEW                        STALE_PERCENT
40

 

# 통계 수집을 못하게 락을 거는 방법

exec dbms_stats.lock_table_stats('hr', 'emp_new')

 

#) lock 이 걸려 있는지 확인 

select stattype_locked from dba_tab_statistics where owner = 'HR' and table_name = 'EMP_NEW';
STATT
-----
ALL

=> ALL: 락이 걸려있다. 

#) 오류발생

exec dbms_stats.gather_table_stats(ownname =>'hr', tabname => 'emp_new', degree => 2)
BEGIN dbms_stats.gather_table_stats(ownname =>'hr', tabname => 'emp_new', degree => 2); END;

*
ERROR at line 1:
ORA-20005: object statistics are locked (stattype = ALL)
ORA-06512: at "SYS.DBMS_STATS", line 24281
ORA-06512: at "SYS.DBMS_STATS", line 24332
ORA-06512: at line 1

=> 해당 table에 lock이 걸려 있어서 통계 수집을 할 수 없다.

# 통계 수집의 lock 해지 방법

exec dbms_stats.unlock_table_stats('hr', 'emp_new')

 

#) lock 이 걸려 있는지 확인. 

select stattype_locked from dba_tab_statistics where owner = 'HR' and table_name = 'EMP_NEW';
STATT
-----


#) 실행 성공

exec dbms_stats.gather_table_stats(ownname =>'hr', tabname => 'emp_new', degree => 2)
PL/SQL procedure successfully completed.
728x90
반응형
LIST