태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

Dynamic Sampling and Concatenation

오라클 2008.07.17 13:16
아래와 같은 고약한 사례가 있다.

t1.c1과 t1.c2 컬럼은 상호 의존적(Correlated)이다. Oracle은 이런 상호 의존적인 컬럼에 대해서는 정확한 Cardinality를 계산하지 못한다.

drop table t1 purge;

create table t1(c1 varchar2(10), c2 varchar2(10));

-- create some correlated columns
insert into t1
select 'A', 'a'
from dual
connect by level <= 10000
;

insert into t1
select 'B', 'b'
from dual
connect by level <= 1000
;

create index t1_n1 on t1(c1);

@gather t1

실제로 다음과 같이 Plan을 떠보면 매우 부정확한 예측을 한다.

explain plan for -- 거의 0건이 나와야 한다.
select /*+ index(t1) use_concat */ *
from t1
where (c1 like 'A%' or c1 like 'C%') and c2 = 'b'
;

@plan

------------------------------------------------------
| Id  | Operation                    | Name  | Rows  |
------------------------------------------------------
|   0 | SELECT STATEMENT             |       |  4125 |
|   1 |  CONCATENATION               |       |       |
|*  2 |   TABLE ACCESS BY INDEX ROWID| T1    |  2750 |
|*  3 |    INDEX RANGE SCAN          | T1_N1 |  5500 |
|*  4 |   TABLE ACCESS BY INDEX ROWID| T1    |  1375 |
|*  5 |    INDEX RANGE SCAN          | T1_N1 |  5500 |
------------------------------------------------------

왜 그런가? c1, c2 컬럼이 상호 의존적이지만 Oracle은 알 수 없기 때문이다. 이런 경우 dynamic_sampling Hint를 사용하면 문제를 해결할 수 있다는 사실을 아래 글에서 다룬 바 있다.

2008/03/06 - [Advanced Oracle] - DYNAMIC_SAMPLING 힌트의 정체

이  예제에서도 dynamic_sampling Hint를 사용해 문제를 해결할 수 있는지 확인해 보자.

explain plan for
select /*+ dynamic_sampling(t1 4) index(t1) use_concat */ *
from t1
where (c1 like 'A%' or c1 like 'C%') and c2 = 'b'
;

@plan

------------------------------------------------------
| Id  | Operation                    | Name  | Rows  |
------------------------------------------------------
|   0 | SELECT STATEMENT             |       |  4125 |
|   1 |  CONCATENATION               |       |       |
|*  2 |   TABLE ACCESS BY INDEX ROWID| T1    |  2750 |
|*  3 |    INDEX RANGE SCAN          | T1_N1 |  5500 |
|*  4 |   TABLE ACCESS BY INDEX ROWID| T1    |  1375 |
|*  5 |    INDEX RANGE SCAN          | T1_N1 |  5500 |
------------------------------------------------------

웁스. 전혀 문제가 해결되지 않았다. 왜 그런가? Dynamic Sampling에 우리가 모르는 무슨 한계가 있는 것인가?

그 이유는 Predicate Information을 보면 알 수 있다.

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

   2 - filter("C2"='b')
   3 - access("C1" LIKE 'C%')
       filter("C1" LIKE 'C%')
   4 - filter("C2"='b')
   5 - access("C1" LIKE 'A%')
       filter("C1" LIKE 'A%' AND LNNVL("C1" LIKE 'C%'))

Dynamic Sampling이 이루어진 조건은 아래와 같다.

where (c1 like 'A%' or c1 like 'C%') and c2 = 'b'

하지만, Or Expansion(Concatentation) 변환에 의해 Query가 다음과 같이 변경되어 버린 것과 같은 효과가 생긴다.


select ...
where (c1 like 'A%' and c2 = 'b')
union all
select ...
where (c1 like 'C%' and c2 = 'b')

위의 조건에 대해서는 Dynamic Sampling이 이루어진 바가 없으므로 Dynamic Sampling에 의해 계산된 값을 사용하지 못하고, Segment Statistics에 있는 값을 그대로 사용할 수 밖에 없는 것이다. 이 문제를 해결하려면 Union All로 재작성(Rewrite)하거나 더 좋은 방법은 Or Expansion을 사용하지 않는 것이다.

어떤 기능이든지 사용할 때는 항상 제약 사항이 없는지 확인해야 한다는 것을 다시 한번 상기시키는 예라고 할 수 있겠다.


PS) 원래 이 글은 다른 내용으로 쓰였는데, 테스트가 잘못 되어 잘못된 결론을 도출한 것을 알았습니다. 그래서 수정해서 다시 올렸음을 알려 드립니다.

'오라클' 카테고리의 다른 글

Why can't I capture my binds?  (2) 2008.07.24
Web에서 Code Style 사용하기  (1) 2008.07.23
Dynamic Sampling and Concatenation  (0) 2008.07.17
Read Consistency In Function  (2) 2008.07.14
Why Creativity Matters?  (0) 2008.07.07
Trackback 0 : Comment 0

Write a comment

티스토리 툴바