drop table t1;
begin
begin execute immediate 'purge recyclebin';
exception when others then null;
end;
begin execute immediate 'begin dbms_stats.delete_system_stats; end;';
exception when others then null;
end;
begin execute immediate 'alter session set "_optimizer_cost_model"=io';
exception when others then null;
end;
end;
/
create table t1
pctfree 70
pctused 30
nologging
as
select
mod((rownum-1),20) n1, -- 20 values, scattered
trunc((rownum-1)/500) n2, -- 20 values, clustered
--
mod((rownum-1),25) n3, -- 25 values, scattered
trunc((rownum-1)/400) n4, -- 25 values, clustered
--
mod((rownum-1),25) n5, -- 25 values, scattered for btree
trunc((rownum-1)/400) n6, -- 25 values, clustered for btree
--
lpad(rownum,10,'0') small_vc,
rpad('x',220) padding
from
all_objects
where
rownum <= 10000
;
create bitmap index t1_i1 on t1(n1)
nologging
pctfree 90
;
create bitmap index t1_i2 on t1(n2)
nologging
pctfree 90
;
create bitmap index t1_i3 on t1(n3)
nologging
pctfree 90
;
create bitmap index t1_i4 on t1(n4)
nologging
pctfree 90
;
create index t1_i5 on t1(n5)
nologging
pctfree 90
;
create index t1_i6 on t1(n6)
nologging
pctfree 90
;
begin
dbms_stats.gather_table_stats(
user,
't1',
cascade => true,
estimate_percent => null,
method_opt => 'for all columns size 1'
);
end;
/
n6 : B-tree Index on clustered column with 25 values
select
small_vc
from t1
where n6 = 2
;
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 400 | 5600 | 54 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T1 | 400 | 5600 | 54 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | T1_I6 | 400 | | 9 (0)| 00:00:01 |
-------------------------------------------------------------------------------------
n5 : B-tree Index on scattered column with 25 values
select
small_vc
from t1
where n5 = 2
;
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 400 | 5600 | 304 (1)| 00:00:04 |
|* 1 | TABLE ACCESS FULL| T1 | 400 | 5600 | 304 (1)| 00:00:04 |
--------------------------------------------------------------------------
n4 : Bitmap Index on clustered column with 25 values
select
small_vc
from t1
where n4 = 2
;
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 400 | 5600 | 131 (0)| 00:00:02 |
| 1 | TABLE ACCESS BY INDEX ROWID | T1 | 400 | 5600 | 131 (0)| 00:00:02 |
| 2 | BITMAP CONVERSION TO ROWIDS| | | | | |
|* 3 | BITMAP INDEX SINGLE VALUE | T1_I4 | | | | |
--------------------------------------------------------------------------------------
n3 : Bitmap Index on scattered column with 25 values
select
small_vc
from t1
where n3 = 2
;
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 400 | 5600 | 133 (0)| 00:00:02 |
| 1 | TABLE ACCESS BY INDEX ROWID | T1 | 400 | 5600 | 133 (0)| 00:00:02 |
| 2 | BITMAP CONVERSION TO ROWIDS| | | | | |
|* 3 | BITMAP INDEX SINGLE VALUE | T1_I3 | | | | |
--------------------------------------------------------------------------------------
n3 : Bitmap Index on scattered column with 25 values
-----------------------------------------------------
Access Path: index (AllEqRange)
Index: T1_I3
resc_io: 3.00 resc_cpu: 23214
ix_sel: 0.04 ix_sel_with_filters: 0.04
Cost: 3.00 Resp: 3.00 Degree: 0
Access path: Bitmap index - accepted
Cost: 133.31 Cost_io: 133.18 Cost_cpu: 1112318 Sel: 0.04
Not believed to be index-only
Best:: AccessPath: IndexBitmap
Cost: 133.31 Degree: 1 Resp: 133.31 Card: 400.00 Bytes: 0
n4 : Bitmap Index on clustered column with 25 values
-----------------------------------------------------
Access Path: index (AllEqRange)
Index: T1_I4
resc_io: 1.00 resc_cpu: 8171
ix_sel: 0.04 ix_sel_with_filters: 0.04
Cost: 1.00 Resp: 1.00 Degree: 0
Access path: Bitmap index - accepted
Cost: 131.31 Cost_io: 131.18 Cost_cpu: 1097275 Sel: 0.04
Not believed to be index-only
Best:: AccessPath: IndexBitmap
Cost: 131.31 Degree: 1 Resp: 131.31 Card: 400.00 Bytes: 0
--> 책과 다름
select
small_vc
from
t1
where
n1 = 2 -- one in 20
and n3 = 2 -- one in 25
;
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 20 | 340 | 13 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID | T1 | 20 | 340 | 13 (0)| 00:00:01 |
| 2 | BITMAP CONVERSION TO ROWIDS| | | | | |
| 3 | BITMAP AND | | | | | |
|* 4 | BITMAP INDEX SINGLE VALUE| T1_I3 | | | | |
|* 5 | BITMAP INDEX SINGLE VALUE| T1_I1 | | | | |
--------------------------------------------------------------------------------------
select
small_vc
from
t1
where
n2 = 2 -- one in 20
and n4 = 2 -- one in 25
;
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 20 | 340 | 9 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID | T1 | 20 | 340 | 9 (0)| 00:00:01 |
| 2 | BITMAP CONVERSION TO ROWIDS| | | | | |
| 3 | BITMAP AND | | | | | |
|* 4 | BITMAP INDEX SINGLE VALUE| T1_I4 | | | | |
|* 5 | BITMAP INDEX SINGLE VALUE| T1_I2 | | | | |
--------------------------------------------------------------------------------------
--> 책과 다름
ex) 3천6백만 로우, 800M(107,543블록), 6가지의 속성 및 비트맵 인덱스를 가지는 테이블
sex = 1
and eyes = 1
and hair = 1
and town = 15
and age = 25
and work = 40
추측비용 (목표치는 314) =
74 * 1.1 * 3 + (가장 비용이 낮은 인덱스를 1.1배 증가시켜서 세 번 사용)
0.8 * 313 / 355 + (로우의 80%는 블록 당 335개씩 모여있음)
0.2 * 313 = (로우의 20%는 개별 블록에 흩어져 있음)
244.2 + 62.6 + 0.75 = 307.55 (에러율 2.1%)
alter table t1 modify n1 not null;
select
small_vc
from
t1
where
n1 != 2 -- one in 20, scattered
and n3 = 3 -- one in 25, scattered
;
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 380 | 6460 | 130 (0)| 00:00:02 |
| 1 | TABLE ACCESS BY INDEX ROWID | T1 | 380 | 6460 | 130 (0)| 00:00:02 |
| 2 | BITMAP CONVERSION TO ROWIDS| | | | | |
| 3 | BITMAP MINUS | | | | | |
|* 4 | BITMAP INDEX SINGLE VALUE| T1_I3 | | | | |
|* 5 | BITMAP INDEX SINGLE VALUE| T1_I1 | | | | |
--------------------------------------------------------------------------------------
alter table t1 modify n1 null;
select
small_vc
from
t1
where
n1 != 2 -- one in 20, scattered
and n3 = 3 -- one in 25, scattered
;
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 380 | 6460 | 127 (0)| 00:00:02 |
| 1 | TABLE ACCESS BY INDEX ROWID | T1 | 380 | 6460 | 127 (0)| 00:00:02 |
| 2 | BITMAP CONVERSION TO ROWIDS | | | | | |
| 3 | BITMAP MINUS | | | | | |
| 4 | BITMAP MINUS | | | | | |
|* 5 | BITMAP INDEX SINGLE VALUE| T1_I3 | | | | |
|* 6 | BITMAP INDEX SINGLE VALUE| T1_I1 | | | | |
|* 7 | BITMAP INDEX SINGLE VALUE | T1_I1 | | | | |
---------------------------------------------------------------------------------------
BITMAP MINUS
오라클은 bitmap minus를 수행할 때, 먼저 두 번째 비트맵을 취해서 1은 0으로, 0은 1로 각각 바꾼다.
그리고 이렇게 뒤바뀐 bitmap을 사용하여 bitmap and를 수행함으로써 bitmap minus 연산을 처리한다.
create table t1
as
with generator as (
select --+ materialize
rownum id
from all_objects
where rownum <= 3000
)
select
/*+ ordered use_nl(v2) */
decode(
mod(rownum-1,1000),
0, rownum - 1,
null
) n1,
decode(
mod(rownum-1,1000),
0, rownum - 1,
null
) n2,
lpad(rownum-1,10,'0') small_vc
from
generator v1,
generator v2
where
rownum <= 1000000
;
create bitmap index t1_i1 on t1(n1);
create bitmap index t1_i2 on t1(n2);
begin
dbms_stats.gather_table_stats(
user,
't1',
cascade => true,
estimate_percent => null,
method_opt => 'for all columns size 1'
);
end;
/
select
small_vc
from
t1
where
n1 = 50000
;
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID | T1 | 1 | 13 | 1 (0)| 00:00:01 |
| 2 | BITMAP CONVERSION TO ROWIDS| | | | | |
|* 3 | BITMAP INDEX SINGLE VALUE | T1_I1 | | | | |
--------------------------------------------------------------------------------------
select
small_vc
from
t1
where
n1 = 50000
or n2 = 50000
;
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1999 | 25987 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID | T1 | 1999 | 25987 | 2 (0)| 00:00:01 |
| 2 | BITMAP CONVERSION TO ROWIDS| | | | | |
| 3 | BITMAP OR | | | | | |
|* 4 | BITMAP INDEX SINGLE VALUE| T1_I1 | | | | |
|* 5 | BITMAP INDEX SINGLE VALUE| T1_I2 | | | | |
--------------------------------------------------------------------------------------
select
small_vc
from
t1
where
n1 = 50000
or (n2 = 50000 and n2 is not null)
;
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1000 | 13000 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID | T1 | 1000 | 13000 | 2 (0)| 00:00:01 |
| 2 | BITMAP CONVERSION TO ROWIDS| | | | | |
| 3 | BITMAP OR | | | | | |
|* 4 | BITMAP INDEX SINGLE VALUE| T1_I1 | | | | |
|* 5 | BITMAP INDEX SINGLE VALUE| T1_I2 | | | | |
--------------------------------------------------------------------------------------
select
small_vc
from
t1
where
(n1 = 50000 and n1 is not null)
or (n2 = 50000 and n2 is not null)
;
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID | T1 | 1 | 13 | 2 (0)| 00:00:01 |
| 2 | BITMAP CONVERSION TO ROWIDS| | | | | |
| 3 | BITMAP OR | | | | | |
|* 4 | BITMAP INDEX SINGLE VALUE| T1_I1 | | | | |
|* 5 | BITMAP INDEX SINGLE VALUE| T1_I2 | | | | |
--------------------------------------------------------------------------------------
select
/*+ index(t1) */
small_vc
from
t1
where
n4 = 2
;
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 400 | 5600 | 127 (1)| 00:00:02 |
| 1 | TABLE ACCESS BY INDEX ROWID | T1 | 400 | 5600 | 127 (1)| 00:00:02 |
| 2 | BITMAP CONVERSION TO ROWIDS| | | | | |
|* 3 | BITMAP INDEX SINGLE VALUE | T1_I4 | | | | |
--------------------------------------------------------------------------------------
select
small_vc
from
t1
where
n6 = 2
;
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 400 | 5600 | 54 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T1 | 400 | 5600 | 54 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | T1_I6 | 400 | | 9 (0)| 00:00:01 |
-------------------------------------------------------------------------------------
--> 책과 다름
– 10053 트레이스
****** trying bitmap/domain indexes ******
Access Path: index (AllEqRange)
Index: T1_I4
resc_io: 1.00 resc_cpu: 8171
ix_sel: 0.04 ix_sel_with_filters: 0.04
Cost: 1.00 Resp: 1.00 Degree: 0
Access path: Bitmap index - accepted
Cost: 126.57 Cost_io: 126.27 Cost_cpu: 1062271 Sel: 0.04
Not believed to be index-only
Best:: AccessPath: IndexBitmap
Cost: 126.57 Degree: 1 Resp: 126.57 Card: 400.00 Bytes: 0
Access Path: index (AllEqRange)
Index: T1_I6
resc_io: 54.00 resc_cpu: 573408
ix_sel: 0.04 ix_sel_with_filters: 0.04
Cost: 54.16 Resp: 54.16 Degree: 1
****** trying bitmap/domain indexes ******
Best:: AccessPath: IndexRange Index: T1_I6
Cost: 54.16 Degree: 1 Resp: 54.16 Card: 400.00 Bytes: 0
비트맵 조인 인덱스
create bitmap index fct_dim_name on fact_table(dim.dim_name)
from
dim_table dim,
fact_table fct
where
dim.id = fct.dim_id
;
create bitmap index fct_dim_par on fact_table(dim.par_name)
from
dim_table dim,
fact_table fct
where
dim.id = fct.dim_id
;
select
count(fct.id)
from
dim_table dim,
fact_table fct
where
dim.par_name = 'Parent_001'
and fct.dim_id = dim.id
;
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 9 | 2149 |
| 1 | SORT AGGREGATE | | 1 | 9 | |
| 2 | TABLE ACCESS BY INDEX ROWID | FACT_TABLE | 10000 | 90000 | 2149 |
| 3 | BITMAP CONVERSION TO ROWIDS| | | | |
|* 4 | BITMAP INDEX SINGLE VALUE | FCT_DIM_PAR | | | |
-----------------------------------------------------------------------------
- 이 쿼리가 10,000개의 로우를 리턴할 것이고 결정했다.
- 80/20 분할을 적용하여 계산하면 2,242개의 블럭을 방문해야 한다.
(이 정도는 db_file_multiblock_read_count 조정에 따른 오차범위에 들어온다)
h3. 비트맵 변환
- 비트맵 인덱스는 본질적으로(정교하게 패키지된) 0과 1의 2차원 배열이다. 배열의 각 컬럼은 인덱스 키의
distinct 값 중 하나에 해당하며, 배열의 각 로우는 테이블 내 특정 로우의 위치에 해당한다.
- 배열의 엔트리를 테이블 엔트리로 변환하는 계산이 bitmap conversion 계산이다.
- bitmap conversion(to rowids) : 배열에서 테이블 쪽으로 변환하는 경우
- bitmap conversion(from rowids) : B-tree to bitmap conversion
{code:sql}
select
small_vc
from
t1
where
n1 = 33
and n2 = 21
;
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 400 | 6800 | 183 |
| 1 | TABLE ACCESS BY INDEX ROWID | T1 | 400 | 6800 | 183 |
| 2 | BITMAP CONVERSION TO ROWIDS | | | | |
| 3 | BITMAP AND | | | | |
| 4 | BITMAP CONVERSION FROM ROWIDS| | | | |
|* 5 | INDEX RANGE SCAN | T1_I1 | | | 41 |
| 6 | BITMAP CONVERSION FROM ROWIDS| | | | |
|* 7 | INDEX RANGE SCAN | T1_I2 | | | 41 |
--------------------------------------------------------------------------
select
d1,
count(*)
from
t1
where
n1 = 2
and d1 between to_date('&m_today', 'DD-MON-YYYY')
and to_date('&m_future','DD-MON-YYYY')
group by
d1
;
m_today의 값을 입력하십시오: 20090101
구 8: and d1 between to_date('&m_today', 'DD-MON-YYYY')
신 8: and d1 between to_date('20090101', 'DD-MON-YYYY')
m_future의 값을 입력하십시오: 20090131
구 9: and to_date('&m_future','DD-MON-YYYY')
신 9: and to_date('20090131','DD-MON-YYYY')
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 394 | 4334 | 57 |
| 1 | HASH GROUP BY | | 394 | 4334 | 57 |
|* 2 | FILTER | | | | |
|* 3 | VIEW | index$_join$_001 | 500 | 5500 | 37 |
|* 4 | HASH JOIN | | | | |
| 5 | BITMAP CONVERSION TO ROWIDS| | 500 | 5500 | 2 |
|* 6 | BITMAP INDEX RANGE SCAN | T1_D1 | | | |
| 7 | BITMAP CONVERSION TO ROWIDS| | 500 | 5500 | 28 |
|* 8 | BITMAP INDEX SINGLE VALUE | T1_N1 | | | |
------------------------------------------------------------------------------------