7. 비용
2011.05.01 17:47
- 옵티마이저가 사용하는 비용 모델
I/O |
- I/O 요청 횟수 |
CPU |
- I/O 요청 횟수 + CPU 시간 |
비고 |
if 9i and optimizer_cost_mode=CHOOSE /*CHOOSE가 기본값<->IO */ if (시스템통계 있으면) then CPU 비용 모델 else I/O 비용 모델 if 10g then CPU 비용 모델 + 시스템 통계(없으면 NoWorkload 시스템 통계) * query 레벨에서 비용 모델 선택하는 힌트 => cpu_costing, no_cpu_costing |
(1) I/O 비용 모델 - I/O call 횟수(논리적/물리적 읽은 블록 횟수가 아닌 I/O call 횟수)
■ Single Block I/O 일 경우 비용 실험
- 인덱스를 경유할 경우는 : 물리적 블록 개수가 I/O 호출 횟수와 일치한다.
- 모든 I/O 호출이 디스크 I/O를 일으키지는 않는다.(이미 메모리에 있는 블록들도 있다)
# ch03_07.txt 실험 => 결과는 첨부파일 ch03_07.hwp 참조 SQL> create table t 2 as 3 select * from all_objects; 테이블이 생성되었습니다. SQL> create index t_owner_idx on t(owner); 인덱스가 생성되었습니다. SQL> begin 2 dbms_stats.gather_table_stats(user, 'T' 3 , method_opt=>'for all columns size 1'); 4 end; 5 / PL/SQL 처리가 정상적으로 완료되었습니다. SQL> alter session set "_optimizer_cost_model" = io; 세션이 변경되었습니다. SQL> set autotrace traceonly exp; SQL> SQL> select /*+ index(t) */ * from t where owner = 'SYS'; Execution Plan --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes| Cost | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 2385 | 216K | 70 | | 1 | TABLE ACCESS BY INDEX ROWID| T | 2385 | 216K | 70 | |* 2 | INDEX RANGE SCAN | T_OWNER_IDX | 2385 | | 6 | --------------------------------------------------------------------------- |
(설명) 비용=6(인덱스)+64(테이블)=70, Rows=2385 Rows가 2385번이므로 2385번의 call이 발생해야하지만 클러스터링 팩터가 비용계산에 반영되었기 때문에 64번 발생
|
■ 인덱스를 이용한 테이블 접근시 비용 식
비용 = blevel + (리프블록수 * 유효인덱스 선택도) + (클러스터링 팩터 * 유효 테이블 선택도) blevel : 브랜치 레벨 유효인덱스선택도 : 방문할 리프 블록 비율(Access Predicate에 의해 결정) 유효테이블선택도 : 방문할 테이블 블록 비율(Access Predicate와 Filter Predicate에 의해 결정) 인덱스 Access Predicate와 인덱스 Filter Predicate가 다른 경우 - 좌변컬럼을 가공한 조건절 - 안쪽 % 또는 양쪽 % 기호를 사용한 like 조건절 - 같은 컬럼에 대한 조건절이 2개 이상일 때, 인덱스 액세스 조건으로 선택되지 못한 다른 조건절 |
(예제의 비용 계산) - 교재 436 페이지 값을 가정할 경우(실험마다 다름) 비용 = 1 + 116*(1/21) + 1337*(1/21) = 70.12
|
■ Full Scan에 의한 테이블 접근 비용
- db_file_multiblock_read_count 인자로 나눈만큼 I/O 호출이 발생한다.
db_file_multiblock_read_count |
rows |
bytes |
cost |
2 |
2385 |
216K |
269 |
4 |
2385 |
216K |
171 |
8 |
2385 |
216K |
109 |
16 |
2385 |
216K |
70 |
32 |
2385 |
216K |
45 |
64 |
2385 |
216K |
29 |
128 |
2385 |
216K |
19 |
■ I/O 비용 모델에 대한 비현실적인 가정
가정 |
Single Block I/O와 Multiblock I/O는 비용이 같다. 캐싱 효과를 전혀 고려하지 않는다. |
수정 파라 메터 |
optimizer_index_cost_adj - 인덱스 탐색 비용을 조정할 때 사용한다. - 값의 범위는 1~10000 이다 - 기본값 : 100 ( 한번의 I/O call을 통해 Single Block Read 방식으로 한 블록을 읽는 비용과 Multiblock Read 방식으로 여러 블럭을 읽는 비용을 같게 평가한다.) 예) optimizer_index_cost_adj = 25 : Single Block Read 방식의 I/O call비용을 Multiblock Read 방식의 I/O call비용의 25% 간주한다. - 인덱스를 경유할 때의 물리적 I/O비용(Single Block Read)을 Full Table Scan할 때의 물리적 I/O 비용(Multiblock Read)과 대비한 상대적 비용을 표현한다. - 이 값을 낮게 설정할수록 옵티마이저는 테이블 스캔보다 인덱스를 이용한 테이블 액세스를 선호하게 된다. |
optimizer_index_caching - NL조인에서 inner쪽 인덱스 블록이 캐싱돼 있을 가능성을 옵티마이저에게 알려주는 파라미터이다. - 값의 범위는 0~100이다.(0은 캐싱이 안되있어서 디스크에서 읽을 경우 가정) - 이 값을 높게 설정할수록 옵티마이저는 인덱스를 이용한 NL조인을 선호하게 된다. |
(2) CPU 비용 모델 - 9i부터 사용됨
■ CPU 시간이 많이 소요되는 경우 : 블록 I/O가 소량인데도 쿼리 수행 시간이 오래 걸리는 경우
- 해시 조인할 때, 해시 체인에 달린 레코드가 많아 해시 체인을 스캔하는 부하가 심할 때 - 캐싱된 블록을 반복적으로 읽는데, 한 블록 내에서 매번 비효율적으로 많은 레코드를 스캔할 때 ( NL조인 inner쪽 인덱스 선두 컬럼이 between 조건일 때) - 버퍼를 Pin한 상태에서 같은 블록을 반복 액세스할 때 - 다량의 레코드를 읽으면서 건건이 여러 개의 사용자 정의 함수를 반복 호출할 때 - 메모리 소트를 반복할 때 - 조건절 개수가 아주 많을 때 - 조건절이나 select-list에 연산 집약적인 작업을 많이 포함할 때 |
■ CPU 비용계산식
비용 = ( #SRds * sreadtim + #MRds * mreadtim + #CPUCycles / cpuspeed ) / sreadtim #SRds : Single Block I/O 요청 횟수 #MRds : Multiblock I/O 요청 횟수 #CPUCycles : 쿼리 수행에 필요한 예상 CPU 사이클 수 sreadtim : Single Block I/O에 소요되는 시간(ms) mreadtim : Multi Block I/O에 소요되는 시간(ms) cpuspeed : 초당 처리할 수 있는 CPU 사이클 수 * sreadtim, mreadtim, cpuspeed 값은 시스템 통계수집시 결정 - Single Block I/O 요청 횟수, Multiblock I/O 요청 횟수에 미리 측정해 놓은 평균 소요시간(sreadtim, mreadtim)을 각각 곱합으로써 I/O일량을 시간으로 표현하였다. - 인덱스 스캔에 의한 테이블 액세스 비용과 테이블 스캔 비용 간에 상대적인 시간 차이가 있음을 계산식에 포함시켰다. - CPU 비용은 쿼리 수행에 필요한 예상 CPU 사이클 수를 초당 처리할 수 있는 CPU 사이클 수로 나눈 값으로 CPU비용을 계산하였다. - I/O 시간과 CPU연산 시간을 더한 시간 개념을 빌어 쿼리 수행 비용을 평가하는 것이 CPU 비용 모델의 핵심이다. - I/O 시간과 CPU 연산 시간을 더한 값을 Single Block I/O에 소요되는 시간으로 나눔으로써 Single Block I/O에 소요되는 시간간의 상대적인 시간 비용을 표현한다. - 즉, CPU 비용 모델의 비용은 쿼리의 예상 총 수행 시간을 Single Block I/O 시간 단위로 표현한 것이라고 할 수 있다. - 10g에서는 user_tab_statistics테이블을 조회하면 테이블별로 캐싱된 블록 수와 캐시 히트율을 얻을 수 있다. 오라클은 캐싱 효과를 비용 계산식에 포함하려는 움직임을 보이고 있으나 아직 반영되지는 않았다. select table_name, avg_cached_blocks, avg_cache_hit_ratio from user_tab_statistics; |
- 오라클 고도화 원리와 해법 2 (bysql.net 2011년 1차 스터디)
- 작성자: 박우창 (balto)
- 최초작성일: 2011년 5월 1일
- 본문서는 bysql.net 스터디 결과입니다 .본 문서를 인용하실때는 출처를 밝혀주세요. http://www.bysql.net
- 문서의 잘못된 점이나 질문사항은 본 문서에 댓글로 남겨주세요. ^^
댓글 0
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
35 |
1. 옵티마이저
![]() | 휘휘 | 2011.04.17 | 6189 |
34 | 3. 옵티마이저의 한계 - P | 휘휘 | 2011.04.17 | 3735 |
33 | 2. 옵티마이저 행동에 영향을 미치는 요소 | balto | 2011.04.17 | 6197 |
32 | 3. 옵티마이저의 한계 | 휘휘 | 2011.04.19 | 6735 |
31 |
4. 통계정보 Ⅰ
![]() | 토시리 | 2011.04.24 | 16114 |
30 | 6. 히스토그램 | 오예스 | 2011.04.25 | 17672 |
29 | 5. 카디널리티 | 오라클잭 | 2011.04.26 | 13001 |
» |
7. 비용
![]() | balto | 2011.05.01 | 5120 |
27 | 8. 통계정보 Ⅱ | AskZZang | 2011.05.04 | 5946 |
26 | 1. 쿼리 변환이란? | 운영자 | 2011.05.16 | 6296 |
25 | 3. 뷰 Merging | 오라클잭 | 2011.05.17 | 6114 |
24 | 2. 서브쿼리 Unnesting | 토시리 | 2011.05.17 | 2116 |
23 |
5. 조건절 이행
![]() | balto | 2011.05.29 | 5500 |
22 | 4. 조건절 Pushing | 오예스 | 2011.05.31 | 17747 |
21 | 6. 조인 제거 | AskZZang | 2011.06.01 | 5484 |
20 | 7. OR-Expansion | AskZZang | 2011.06.01 | 8468 |
19 | 12. 기타 쿼리 변환 | 휘휘 | 2011.06.05 | 3185 |
18 | 10. 실체화 뷰 쿼리로 재작성 | 오라클잭 | 2011.06.07 | 9996 |
17 | 11. 집합 연산을 조인으로 변환 | 오라클잭 | 2011.06.07 | 4993 |
16 |
2. 소트를 발생시키는 오퍼레이션
![]() | balto | 2011.06.11 | 4890 |