- DB 제작시 maintenance autotask 설정에 자동으로 통계 수집
- chain_cnt : migration의 횟수
- Noworkload 통계 : 인스턴스를 진행하며 1번 수집
- workload 통계 : 자동으로 수집
- 시스템 통계는 제대로 된 workload에서 한번만 수집해 놓음
- 테이블 통계
- 행 수, 블록 수, 평균 행 길이, 통계 상태
- 상태 : 마지막 통계 이후에 얼마나 변했는가
- B*-트리 레벨
- 최하위 블록 수 -> 트리 레벨과 합치면 깊이
- 인덱스 클러스터링 요소 : 데이터를 읽을 때, 한 블럭안에 모여있어서 그것만 읽어서 결과를 볼 수 있다면 좋음
- 컬럼이 조건절에 사용되는 비중까지 고려해서 통계 수집 가능
- 통계 수집시 설정한 기본값은 저장됨
- exec dbms_stats.gather_table_stats('HR','EMPLOYEE', method_opt=>'for all columns size auto') -> 위치지정 방식과 이름지정 방식 = hybrid
- 자동 수집을 방지 -> 변화하는 것을 원치 않음
- 주로 휘발성 테이블에 사용됨
- 통계 복원 : 과거의 통계로 되돌리는 기능
- exec dbms_stats.gather_table_stats(user,'SALES'); -> 현재 유저의 SALES 테이블의 통계 수집
- select table_name, stattype_locked, last_analyzed
- from dba_tab_statistics
- where owner='USER01' and table_name='SALES'; -> last_analyzed가 방금 시간으로 되어있음
- exec dbms_stats.delete_table_stats(user,'SALES'); -> 현재 저장되어 있는 통계를 제거
- 다시 통계 생성 후 lock 걸기 -> exec dbms_stats.lock_table_stats(user,'SALES');
- lock이 걸렸을 때는 통계를 수집 못함
- unlock -> exec dbms_stats.unlock_table_stats(user,'SALES');
- dba_tab_stats_history : 31일간의 통계가 자동으로 저장되어 있음
- delete시 현재 통계만 지워지고 기록은 남아있음
- dba_tab_stats_history에서 통계가 생성된 시간을 복사
- exec dbms_stats.restore_table_stats(user,'SALES',as_of_timestamp=>'시간');
- 데이터 뿐만 아니라 통계도 함께 export, import
- DBMS_STATS 프로시저 사용
- create_stat_table은 통계 테이블을 생성
- export_*_stats는 통계를 통계 테이블로 집어 넣음
- data pump로 통계 테이블을 이동
- import_*_stats는 통계를 데이터 딕셔너리로 이동
바인드 변수 사용
- 라이브러리 캐시에 서로 다른 sql문장들의 실행계획들이 저장됨
- 커서 공유하지 않아 실행계획이 동일하더라도 각각 parsing
- 커서가 공유되어 parsing을 새로하지 않고 1개의 실행계획으로 처리 가능
- 한 sql 문이 반복적으로 실행되는 경우
- 실행시간이 짧은 경우
- 더 좋은 실행계획이 존재하더라도 미리 만들어진 실행계획을 사용하는 경우가 생김
- 실습
- alter system flush shared_pool; -> shared_pool을 비움
- alter system flush buffer_cache; -> 버퍼를 비움
- select sql_id, sql_text, parse_calls, loads, executions, invalidations
- from v$sql
- where sql_text like '%CURSOR_TEST%'
- and sql_text not like '%v$sql%'; -> parsing된 것들 확인 가능
- select /*+ CURSOR_TEST */ * from emp where empno=101; -> where절의 숫자를 바꾸며 여러번 실행하더라도 cursor 공유가 되지않아 parsing을 매번 실행함
- 바인드 변수를 사용하면 cursor 공유 가능 -> variable b_no number
- exec :b_no = 7788;
- select /*+ CURSOR_TEST */ * from emp where empno = :b_no;
- 7788, 7900 등 값들 입력
- 다시 v$sql을 확인해보면 하나의 parse만 존재하는 것을 확인 가능
- parse_calls : 몇 번 시도 했는지
- 첫 번째 문장을 parsing할 때, 바인드 변수를 확인하여 실행계획을 공유
- 오라클이 알아서 판단하여 실행하기 때문에 현실 데이터와는 동떨어진 parsing을 할 수 있음
- 현실적인 값을 반영하기 위해 사용
- 처음에 오는 값이 현실성과 동떨어진 데이터라도 그 실행계획을 그대로 사용하기 때문에 문제가 생김
- 적응적 커서 공유
- 첫 번째 실행 계획이 현실과 동떨어진 실행계획이라고 판단되면 다시 실행계획을 세움
- 데이터의 분포도에따라 여러 실행계획을 작성해 놓고 데이터에 맞게 사용
- 조건
- bind variable 사용
- bind variable peeking 사용
- histogram 정보가 제공되거나 범위 연산일때
- IS_BIND_SENSITIVE : 커서가 바인드에 따른 커서인지
- IS_BIND_AWARE : 커서가 바인드 인식 커서인지
- 서로 다른 실행계획, 맞는 실행계획으로 실행
- 바인드 변수를 사용했을 때의 이야기
- 변수가 아닌 상수들로 sql을 반복 실행 할 때
- exact(기본 값) : 완전히 같을 때만 공유
- force : 바인드 변수를 사용할 때처럼
- similar : 바인드 변수를 사용할 때처럼 하지만 안전한 리터럴에 대한 공유만 발생
- 상수를 쓰지만 오라클 내부에서는 바인드 변수로 바꿔서 사용
- cursor sharing을 exact가 아닌 다른 설정들로 사용한다면 adaptive cursor sharing으로 수행될 것임