핵심 공식!!
Cardinality = Base Cardinality * Selectivity
?
1200명의 청중을 대상으로 이 중에 몇 명이 12월에 태어났겠느냐 물었을 때 CBO적으로 답을 구하는 행동 | {code:sql}select count(*) from auudience 청중 where month_no = 12{code} | ||
1년은 12달이다 | 알려진 사실 | ||
생일은(아마도) 년 중 고르게 분산되어 있을것이다. | 가정 | density or 1/NDV | user_tab_col_statistics.num_distinct = 12 |
청중의 1/12는 어느 특정 월에 태어났을 것이다. | 월의 선택도 | selectivity | user_tab_col_statistics.num_density = 1/12 user_ab_histogram=popular histogram 같은 분포를 가진다. (차라리 히스토그램이 없어서 1/ndv를 사용했다라고하자) |
어느 특정 월을 요청하였다. | 조건 | predicate | month_no=12 |
요청한 월은 실제로 달력에 존재한다. | 경계체크 | month_no=12는 user_tab_col_statistics의 low_value와 high_vlaue사이에 있다. user_tab_col_statistics.num_null = 0 | |
청중은 1200명이다. | 기본 카디널리티 | base cardinality | user_tables.num_rows=1200 |
정답은 1200명의 1/12/인 100명이다. | 계산된 카디날리티 | adjust cardinality | count(*)= 100 |
//온라인코드집(birth_month_01.sql)을 보면 Test의 단순성을 위해서인지 _optimizer_cost_model을 io로 설정했고, 히스토그램 없이 통계정보를 수집했다
create table audience as
selec trunc(dbms_random.value(1,13)) month_no
from all_objects
wher rownum <= 1200
;
begin
dbms_stats.gather_table_stats(
user,
'audience',
cascade => true,
estimate_percent => null,
method_opt => 'for all columns size 1'
);
end;
/
set autotrace traceonly explain
select count(*)
from audience
where month_no = 12
;
위의 예에서 자기 생일을 기억 못하는 청중이 10%라고 가정한다면
select count(*)
from auudience 청중
where month_no = 12
density or 1/NDV | user_tab_col_statistics.num_distinct = 12 |
selectivity | user_tab_col_statistics.num_density = 1/12 user_tab_histogram=popular histogram 같은 분포를 가진다. (차라리 히스토그램이 없어서 1/ndv를 사용했다라고하자) |
predicate | month_no=12 |
num_nulls | month_no=12는 user_tab_col_statistics의 low_value와 high_vlaue사이에 있다. user_tab_col_statistics.num_nulls = 0 -> user_tab_col_statistics.num_null = 120 |
base cardinality | user_tables.num_rows=1200 |
Base Selectivity: 1/12
Num_Nulls = 120
조정된 Cardinality
Adjust Selectivity: Base Selectivity * (num_rows-num_nulls)/num_ros
Adjust Selectivity: (1/12) * ((1200-120)/1200) = 0.075
Adjust Cardinality : 0.075 * 1200 = 90
NULL값이 영향을 주어 조정된 값이 도출된다.
Update audience
Set month = null
Where rowed in (select rid
From (select rowed rid,
, ntil(10) over () nt
From audience)
Where nt = 10);
Commit;
begin
dbms_stats.gather_table_stats(
user,
'audience',
cascade => true,
estimate_percent => null,
method_opt => 'for all columns size 1'
);
end;
/
set autotrace traceonly explain
select count(*)
from audience
where month_no = 12
;?
!table selectivity_2.bmp!
표에서 볼 수 있는 몇 가지 패턴
리터럴을 사용한 범위검색 시의 비공식적인 알고리즘
Selectivity = '요청한 범위' / '전체 대상 범위'
조건이 두개인 쿼리의 일반적인 선택도 계산방법"
※ 오류의 가능성