Oracle FAQ | Your Portal to the Oracle Knowledge Grid |
![]() |
![]() |
Home -> Community -> Mailing Lists -> Oracle-L -> Re: BITMAP index cost 10053 trace (some doubts)
Hi Gopal,
I'm investigating a strange behavior with NL join to a partitioned table with bitmap index (probably similar to the bug 2423599 WRONG COST ESTIMATION WITH BITMAP INDEX, RANGE PARTITION AND NESTED LOOP). BTW the - not very intuitive thing is - on a full partition the bitmap index is used to access the inner table in NL, if the partition is additionally constrained, the bitmap index is *not* used.
I took a closer look on the bitmap index costing and I encountered some strange results.
> Let us take another case where an index has 100,000 rows from a table
> with an average of 50 rows per block (for a total of 2,000 blocks) and
> the result set expects 1,000 rows.
> In the new costing model, the cost will be (0.8*20) + (0.2*2000), which is
> 56 blocks.
SQL> select (0.8*20) + (0.2*2000) from dual;
(0.8*20)+(0.2*2000)
416
I don't thing it is only a typo. It is probably not very realistic to expect that accessing 200 rows (20% of 1000) will result in 400 table block access (20% of 2000 blocks).
My observation shows that this part of the cost formula (.2 * blocks) is valid only for larger count of selected rows; for smaller count there is some kind correction that lower the cost.
Secondly, I cannot verify the first part of the formula (selected rows * .8 / records_per_block), although a see a strong linear dependency on the selected row count. The test case below - very similar to yours (100.000 rows, 2000 blocks) - gives something like
selected rows * 2 / records_per_block (in my case selected rows * 24,81)
This means instead of 80% of "blocked" rows 200% are considered - this is not very intuitive to me.
In the test case I completely ignored the bitmap index cost, but as they will range between 1 and 9 (= level + LB) this is not an extraordinary error.
Any explanations?
Regards
Jaromir D.B. Nemec
Test case
SQL> @bitmap_cost
SQL> set pagesize 10000
SQL> set pause off
SQL> alter session set nls_language=english;
Session altered.
SQL> -- SQL> select value from v$parameter where name like '%block%size%';
VALUE
16384
SQL> select * from v$version;
BANNER
Oracle9i Enterprise Edition Release 9.2.0.5.0 - Production
PL/SQL Release 9.2.0.5.0 - Production
CORE 9.2.0.6.0 Production
TNS for Linux: Version 9.2.0.5.0 - Production
NLSRTL Version 9.2.0.5.0 - Production
SQL> -- define table with 100.000 rows in 2000 blocks
SQL> --- SQL> drop table x;
Table dropped.
SQL> create table x
2 pctfree 0
3 as
4 select mod(rownum , 100) a, rpad('x',307) b
5 from dual connect by 1=1 and level < 100001;
Table created.
SQL> -- SQL> alter table x minimize records_per_block;
Table altered.
SQL> -- SQL> create bitmap index x_ix1 on x(a);
Index created.
SQL> --- SQL> begin
2 dbms_stats.gather_table_stats
3 ( ownname => user,
4 tabname => 'x',
5 cascade => TRUE );
6 end;
7 /
PL/SQL procedure successfully completed.
SQL> --- SQL> select num_rows, blocks from dba_tables where table_name = 'X' and owner = 'NEMECJ';
NUM_ROWS BLOCKS
100000 1995
SQL> -- SQL> select blevel, leaf_blocks from dba_indexes where table_name = 'X' and owner = 'NEMECJ';
BLEVEL LEAF_BLOCKS
1 8
SQL> ---- explain plan
SQL> delete from nemecj.plan_table a
2 where statement_id like 'N%';
400 rows deleted.
SQL> EXPLAIN PLAN set statement_id = 'N1' into nemecj.plan_table FOR select /*+ INDEX(x)*/ * from x where a <= 1;
Explained.
SQL> EXPLAIN PLAN set statement_id = 'N2' into nemecj.plan_table FOR select /*+ INDEX(x)*/ * from x where a <= 2;
Explained.
SQL> EXPLAIN PLAN set statement_id = 'N96' into nemecj.plan_table FOR select /*+ INDEX(x)*/ * from x where a <= 96;
Explained.
SQL> EXPLAIN PLAN set statement_id = 'N97' into nemecj.plan_table FOR select /*+ INDEX(x)*/ * from x where a <= 97;
Explained.
SQL> EXPLAIN PLAN set statement_id = 'N98' into nemecj.plan_table FOR select /*+ INDEX(x)*/ * from x where a <= 98;
Explained.
SQL> EXPLAIN PLAN set statement_id = 'N99' into nemecj.plan_table FOR select /*+ INDEX(x)*/ * from x where a <= 99;
Explained.
SQL> EXPLAIN PLAN set statement_id = 'N100' into nemecj.plan_table FOR select /*+ INDEX(x)*/ * from x where a <= 100;
Explained.
SQL> --- get the count of selected row, bitmap index (and table) cost and calculate the difference
SQL> select to_number(substr(statement_id,2))*1000 rowset, cost,
2 -- costs difference
3 round(to_number(substr(statement_id,2))*1000 / 24.81 + 0.2 * 1995) - cost cost_diff
4 from nemecj.plan_table a
5 where statement_id like 'N%' and operation = 'SELECT STATEMENT'
6 order by to_number(substr(statement_id,2));
ROWSET COST COST_DIFF
1000 338 101
2000 436 44
3000 511 9
4000 572 -12
5000 624 -23
6000 672 -31
7000 716 -35
8000 758 -37
9000 800 -38
10000 841 -39
11000 881 -39
12000 922 -39
83000 3767 -23
84000 3807 -22
85000 3847 -22
86000 3888 -23
87000 3928 -22
88000 3968 -22
89000 4008 -22
90000 4048 -21
91000 4088 -21
92000 4128 -21
93000 4168 -21
94000 4208 -20
95000 4248 -20
96000 4288 -20
97000 4328 -19
98000 4368 -19
99000 4368 21
100000 4368 62
100 rows selected.
SQL> -- and quit
SQL> quit;
-- http://www.freelists.org/webpage/oracle-lReceived on Sun Jun 05 2005 - 16:34:15 CDT
![]() |
![]() |