
db file scattered read 이벤트가 발생한다.- SQL문을 실제 수행하지 않고 실행계획 출력
set autot traceonly exp
- 실행계획 출력 끄기
set autot offselect * from hr.emp where employee_id = 100;
- filter 검색을 하는건 해당 row를 찾기 위해 full table scan을 하는거다
alter session set db_file_multiblock_read_count=128;select /*+ full(e) parallel(e,2) */ * from hr.emp e;by user rowid, by index rowid를 이용하여 소량의 데이터 검색시 유용하다.
single block I/O 발생
db file sequential read 이벤트가 발생한다.
rowid에서 값 추출
select
employee_id,
rowid,
dbms_rowid.rowid_object(rowid) as data_object_id,
dbms_rowid.rowid_relative_fno(rowid) as file_no,
dbms_rowid.rowid_block_number(rowid) as block_no,
dbms_rowid.rowid_row_number(rowid) as row_clot_no
from hr.emp
where employee_id = 100;

select * from hr.emp where rowid = 'AAASlkAAHAAAAKrAAJ';

- 인덱스 생성
create index hr.emp_idx on hr.emp(employee_id);
- 인덱스 정보 확인
select ix.index_name, ix.uniqueness, ic.column_name
from dba_indexes ix, dba_ind_columns ic
where ix.index_name = ic.index_name
and ix.table_name = 'EMP'
and ix.owner='HR';

- 실행계획 확인
set autot traceonly exp
select * from hr.emp where employee_id =100;

nonunique 이기 때문이다.- hint를 사용해서 의도적으로 full table scan을 유도
select /*+ full(e) */ * from hr.emp e where employee_id=100;

- 컬럼의 형변환을 해도 full table scan을 하게 된다.
select * from hr.emp where to_number(employee_id)=100;

- hint로 index scan 유도
select /*+ index(e emp_idx) */ * from hr.emp e where employee_id = 100;

- hint를 사용하여 의도적으로 index range scan을 유도
select /*+ index_rs(e emp_idx) */ * from hr.emp e where employee_id = 100;

- unique index 먼저 생성
create unique index hr.emp_idx on hr.emp(employee_id);
- 인덱스 이름과 제약조건을 이름을 다르게 해야할 경우 인덱스를 먼저 생성 후 제약조건을 후에 생성한다. using index 절 이용
alter table hr.emp add constraint emp_id_pk primary key(employee_id) using index hr.emp_idx;
- 인덱스 정보 확인
select ix.index_name, ix.uniqueness, ic.column_name
from dba_indexes ix, dba_ind_columns ic
where ix.index_name = ic.index_name
and ix.table_name = 'EMP'
and ix.owner='HR';

- 제약조건 확인
select c.column_name, u.constraint_name, u.constraint_type, u.search_condition, u.index_name
from dba_constraints u, dba_cons_columns c
where u.constraint_name = c.constraint_name
and u.table_name='EMP';

- 실행계획 확인
select * from hr.emp where employee_id = 100;'

- 범위스캔 할 경우 실행계획 확인
select * from hr.emp where employee_id between 100 and 101;

- hint로 index scan 유도
select /*+ index(e emp_idx) */ * from hr.emp e where employee_id = 100;

- hint를 사용하여 의도적으로 index range scan을 유도하려고 하였지만 오라클은 unique index 설정이 되어있는데 굳이 range scan을 하려고 하지 않는다.
select /*+ index_rs(e emp_idx) */ * from hr.emp e where employee_id = 100;

- 실행계획을 보게되면 INLIST ITERATOR으로 실행계획이 만들어진다.
select * from hr.emp where employee_id in (100,200);
select * from hr.emp where employee_id = 100 or employee_id = 200;

- inlist iterator 방식은 내부적으로는 union all을 사용한 해당 쿼리문으로 실행된다.
select * from hr.emp where employee_id = 100
union all
select * from hr.emp where employee_id = 200;

- 새로운 nonunique index 생성
create index hr.emp_name_idx on hr.emp(last_name);
select ix.index_name, ix.uniqueness, ic.column_name
from dba_indexes ix, dba_ind_columns ic
where ix.index_name = ic.index_name
and ix.table_name = 'EMP'
and ix.owner='HR';

- 실행계획 확인
select * from hr.emp where last_name='King';

- last_name은 nonunique index가 설정되어 있고, first_name은 인덱스가 설정되어 있지 않다.
select * from hr.emp where last_name='King' and first_name = 'Steven';

- 이전 인덱스 삭제
drop index hr.emp_name_idx;
- 조합 인덱스 생성
create index hr.emp_name_idx on hr.emp(last_name, first_name);
- 인덱스 정보 확인
select ix.index_name, ix.uniqueness, ic.column_name
from dba_indexes ix, dba_ind_columns ic
where ix.index_name = ic.index_name
and ix.table_name = 'EMP'
and ix.owner='HR';

- 조합 인덱스를 이용하기 때문에 access 술어만 이용한다.
select * from hr.emp where last_name='King' and first_name = 'Steven';

- 선행 컬럼인 last_name 만 가지고 검색할때는 문제 없이 index range scan을 한다.
select * from hr.emp where last_name='King';

- 후행 컬럼인 first_name 만 가지고 검색 할때는 index skip scan을 하게 되는데 이 scan은 선행 컬럼을 다 확인하면서 후행컬럼을 검색 하기 때문에 I/O가 좋지 않다.
select * from hr.emp where first_name = 'Steven';

| 선행컬럼 | 후행컬럼 |
|---|---|
| A | steven |
| A | lisa |
| B | nana |
| B | oracle |
| C | koko |
| C | biba |
- hint를 사용해 의도적으로 index skip scan을 유도
select /*+ index_ss(e emp_name_idx) */ * from hr.emp e where first_name='Steven';

- hint를 사용해 index skip scan으로 실행계획을 만들지 말고 index full scan을 유도
select /*+ no_index_ss(e emp_name_idx) */ * from hr.emp e where first_name='Steven';

select last_name, first_name from hr.emp;

- 건수를 셀대도 index full scan을 이용하는데 이때 index는 2가지중 한개를 사용하게 된다. not null제약조건이 있는 index 또는 primary key 제약조건이 있는 index를 사용한다.
select count(*) from hr.emp;

- hint를 사용해 index fast full scan 을 유도
select /*+ index_ffs(e emp_idx) */ count(*) from hr.emp e;

alter session set db_file_multiblock_read_count = 128; select /*+ index_ffs(e emp_idx) parallel_index(e,emp_idx,2) */ count(*) from hr.emp e;
select * from all_synonyms where synonym_name = 'PLAN_TABLE';

- 실행계획을 plan_table 딕셔너리에 저장
explain plan for
select * from hr.emp where employee_id = 100;

- plan_table 딕셔너리에 있는 실행계획을 basic 모드로 보게 되면 심플하게 보여줌
select * from table(dbms_xplan.display(null,null,'basic'));

- typical모드로 보게 되면 더 자세한 실행계획을 보여줌
select * from table(dbms_xplan.display(null,null,'typical'));

Id : 각 Operation 번호, id에 * 있는경우 Predicate Information에 access, filter에 관한 정보
Operation : 실행되는 job
Name : Operation이 액세스하는 테이블, 인덱스
Rows : 각 Operation이 끝났을때 return되는 행수(예상치)
Bytes : 각 Operation이 수행했을때 byte값(예상치)
Cost (%CPU) : 각 Operation의 cost, 누적치(예상치)
Time : 각 Operation의 수행시간, 누적치(예상치)
access predicate : 실제 블록을 읽기전에 어떤 방법으로 블록을 읽을 것인가를 결정(찾고자 하는 행이 있는 블록의 위치를 알고 있을때, 보편적으로 rowid scan을 수행할 경우)
filter predicate : 실제 블록을 읽은 후에 데이터를 걸러내기 위해 사용된다. (찾고자 하는 행이 어느 블록에 있는지 위치를 모를때)
- 내가 임의로 문장아이디를 설정해서 실행계획을 만들 수 있다.
explain plan set statement_id = 'demo1' for
select * from hr.emp where employee_id = 100;

- 실행계획 확인
dbms_xplan.dislay(plan table,문장아이디,조회모드)
select * from table(dbms_xplan.display('plan_table','demo1','typical'));

- query block(가상집합)을 만들어서 실행계획을 만든다.
select * from table(dbms_xplan.display('plan_table','demo1','all'));

- 옵티마이저가 실행계획을 만들때 사용한 hint 확인할수 있는 실행계획 조회
select * from table(dbms_xplan.display('plan_table','demo1','outline'));

- outline하고 all하고 합쳐진 실행계획을 조회
select * from table(dbms_xplan.display('plan_table','demo1','advanced'));

- advanced 에서 outline은 빼고 실행계획 하고 싶을때
select * from table(dbms_xplan.display('plan_table','demo1','advanced -outline'));

@$ORACLE_HOME/sqlplus/admin/plustrce.sql
<<sys session>>
grant plustrace to hr;
<<hr session>>
select * from session_roles;

- SQL문 실제 수행하고 결과와 함께 실행계획, 실행통계 정보 출력
set autotrace on
select * from hr.emp where employee_id = 100;

recursive calls : 유저레벨과 시스템 레벨에서 생성되는 재귀호출의 수
db block gets : DML 작업시에 체크, current한 블록이 요청된 회수를 나타낸다. 메모리에서 access한 블록의 수
consistent gets : SELECT 작업시에 체크, 블록에 대해 일관성 읽기가 요청된 횟수를 나타낸다. 메모리에서 access한 블록의 수, physical reads 수를 포함한다.
physical reads : 디스크에서 읽은 데이터 블록의 수
redo size : DML작업시 사용한 리두 사이즈(byte)
bytes sent via SQL*Net to client : 클라이언트로 보낸 총 바이트값
bytes received via SQL*Net from client : 클라이언트로 받은 바이트값
SQL*Net roundtrips to/from client : 클라이언트와 주고 받은 오라클 NET 메시지 수
sorts (memory) : 메모리에서 수행되어 디스크 쓰기가 필요하지 않은 정렬작업의 수
sorts (disk) : 최소한 하나의 디스크 쓰기가 필요한 정렬 작업의 수
rows processed : 처리된 행의 수