IV. Dynamic Sampling

IV.1. 개념설명

  • cardinality를 제어하는 기법중 하나
  • DYNAMIC_SAMPLING이라는 힌트를 사용

IV.2. 사용 사례


explain plan for
select *
from t2,
 (select /*+ dynamic_sampling(t1 4) */
   c1, c2
  from t1
  where t1.c2 = 'A' and
        t1.c3 = 'b'
 ) v
where t2.c1 = v.cl;


--------------------------------------------------------------------------------------
| Id  | Operation                    | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |       |     1 |    16 |     9   (0)| 00:00:01 |
|   1 |  NESTED LOOPS                |       |       |       |            |          |
|   2 |   NESTED LOOPS               |       |     1 |    16 |     9   (0)| 00:00:01 |
|*  3 |    TABLE ACCESS FULL         | T1    |     1 |     8 |     7   (0)| 00:00:01 |
|*  4 |    INDEX RANGE SCAN          | T2_N1 |     1 |       |     1   (0)| 00:00:01 |
|   5 |   TABLE ACCESS BY INDEX ROWID| T2    |     1 |     8 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------------------

T1 access시 Rows가 1로 정확한 cardinality가 계산됨

적용이 안되는 사례

1. 조건절에 literal 값이 오지 않는 경우


select
  *
from 
  t1
where
  c2 = 'A' and
  c3 = (select max(c2) from t3)
;


----------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |  5000 | 40000 |    10   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL  | T1   |  5000 | 40000 |     7   (0)| 00:00:01 |
|   2 |   SORT AGGREGATE    |      |     1 |     2 |            |          |
|   3 |    TABLE ACCESS FULL| T3   |     2 |     4 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------

  • dynamic sampling을 사용했음에도 불구하고 정확한 cardenality를 계산해 내지 못함
  • dynamic sampling 자체는 동작했지만 c2 = 'A'와 같은 특정 테이블에 대해 Literal의 Predicate가 주어진 경우에만 기대한 것과 같이 동작하기 때문

2. 바인드 변수의 사용 혹은 조인이 사용된 경우


select 
  *
from
  t1, t2
where
  t1.c1 = t2.c1+100000
;


---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      | 11000 |   171K|    15   (7)| 00:00:01 |
|*  1 |  HASH JOIN         |      | 11000 |   171K|    15   (7)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| T1   | 11000 | 88000 |     7   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| T2   | 11000 | 88000 |     7   (0)| 00:00:01 |
---------------------------------------------------------------------------

  • dynamic sampling 자체가 수행되지 않음
  • dynamic sampling은 bind변수에 대해서는 동작할 수 없을 뿐더러 테이블간의 조인은 고려대상이 아니기 때문
  • t1.c1 = :b1 and t2.c1 = :b2와 같이 인식함
  • dynamic sampling 사용시 주의할 점

1. hard parse 시의 오버헤드가 증가한다. (테이블의 블록을 물리적으로 읽어 샘플링을 수행해야 하기 때문이다.)
2. bind 변수 사용시 동작하지 않는다.(bind peeking이 비활성화 되어 있다면 더더욱)
3. DSS용으로 고안된 방법이다.
4. 쿼리 레벨이 아닌 테이블 레벨로 이루어진다.(조인이나 서브쿼리와 같은 복잡한 조건은 처리하지 못한다.)

dynamic sampling은 통계정보가 없는 테이블에 대한 쿼리를 도와주는 역할뿐만 아니라 위와 같이 통계 정보에 대한 해석의 오류에서 오는 실행 계획 이상 현상을 방지할 수 있는 훌륭한 도구가 될 수 있다.