Concatenated Bitmap Indexes Part II (Everybody’s Got To Learn Sometime) May 12, 2010
Posted by Richard Foote in Bitmap Indexes, CBO, Concatenated Indexes, Oracle Cost Based Optimizer, Oracle Indexes.trackback
A basic little post to conclude this discussion.
The issues regarding whether to go for single column indexes vs. concatenated indexes are similar for Bitmap indexes as they are for B-Tree indexes.
It’s generally more efficient to access a concatenated index as it’s only the one index with less processing and less throwaway rowids/rows to contend with. However it’s more flexible to have single column indexes, especially for Bitmap indexes that are kinda designed to be used concurrently, as concatenated indexes are heavily dependant on the leading column being known in queries.
If we look at the second table from Part I which had the concatenated index being significantly larger than the sum of the single column indexes, we notice that it can still have a part to play with the CBO. When we run a query that references both columns in predicates:
SQL> select * from bowie2 where id = 42 and code = 42; 100 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 4165488265 ------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 100 | 1200 | 21 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID | BOWIE2 | 100 | 1200 | 21 (0)| 00:00:01 | | 2 | BITMAP CONVERSION TO ROWIDS| | | | | | |* 3 | BITMAP INDEX SINGLE VALUE | BOWIE2_3_I | | | | | ------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("ID"=42 AND "CODE"=42) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 103 consistent gets 26 physical reads 0 redo size 3030 bytes sent via SQL*Net to client 482 bytes received via SQL*Net from client 8 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 100 rows processed
The CBO favours the concatenated index with the total number of consistent gets at 103. This despite the fact the concatenated index has some 10,000 distinct entries and is somewhat larger than the sum of the single column indexes. If we now drop the concatenated index and re-run the same query:
SQL> drop index bowie2_3_i; Index dropped. SQL> select * from bowie2 where id = 42 and code = 42; 100 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 2338088592 ------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 100 | 1200 | 22 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID | BOWIE2 | 100 | 1200 | 22 (0)| 00:00:01 | | 2 | BITMAP CONVERSION TO ROWIDS| | | | | | | 3 | BITMAP AND | | | | | | |* 4 | BITMAP INDEX SINGLE VALUE| BOWIE2_1_I | | | | | |* 5 | BITMAP INDEX SINGLE VALUE| BOWIE2_2_I | | | | | ------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 4 - access("ID"=42) 5 - access("CODE"=42) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 105 consistent gets 0 physical reads 0 redo size 3030 bytes sent via SQL*Net to client 482 bytes received via SQL*Net from client 8 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 100 rows processed
The CBO can use a BITMAP AND operation by accessing and ANDing the associated bitmap columns from both single column indexes. However this is little less efficient than using the single concatenated index (105 vs 103 consistent gets) even though the concatenated index is somewhat larger than the other 2 indexes combined as Oracle needs to access and process two Bitmap index segments, not one. However as is very common, note in both examples, most of the consistent gets are in relation to getting the 100 rows out of the table, not so much with regard to the indexes themselves.
However, it we just reference the CODE column in a predicate:
SQL> select * from bowie2 where code = 42; 10000 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 2522233487 ------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 10000 | 117K| 489 (1)| 00:00:03 | | 1 | TABLE ACCESS BY INDEX ROWID | BOWIE2 | 10000 | 117K| 489 (1)| 00:00:03 | | 2 | BITMAP CONVERSION TO ROWIDS| | | | | | |* 3 | BITMAP INDEX SINGLE VALUE | BOWIE2_2_I | | | | | ------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("CODE"=42) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 2861 consistent gets 0 physical reads 0 redo size 257130 bytes sent via SQL*Net to client 7742 bytes received via SQL*Net from client 668 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 10000 rows processed
Providing it’s cheaper than other alternatives, the single column bitmap index can be considered and used by the CBO. However, if we only had the previous concatenated index:
SQL> drop index bowie2_1_i; Index dropped. SQL> drop index bowie2_2_i; Index dropped. SQL> create bitmap index bowie2_3_i on bowie2(id,code) pctfree 0; Index created. SQL> select * from bowie2 where code = 42; 10000 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 1495904576 ---------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 10000 | 117K| 497 (6)| 00:00:03 | |* 1 | TABLE ACCESS FULL| BOWIE2 | 10000 | 117K| 497 (6)| 00:00:03 | ---------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("CODE"=42) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 3011 consistent gets 2343 physical reads 0 redo size 165134 bytes sent via SQL*Net to client 7742 bytes received via SQL*Net from client 668 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 10000 rows processed
As the leading column is not specified, the concatenated Bitmap index is ineffective and the CBO decides to use a FTS. So it’s a similar scenario as with B-tree indexes.
A concatenated Bitmap index can potentially use less or more space than corresponding single column Bitmap indexes, it depends on the number of index entries that are derived and the distribution of the data with the table. However regardless, a concatenated Bitmap index can still be a viable alternative if at least the leading column is specified and be the more efficient option if all columns are generally specified, even if the overall size of the index is somewhat greater than the sum of the alternative single column Bitmap indexes. Then again, it’s less flexible and may not be considered if the leading column is not referenced.
If columns are generally all specified in SQL predicates, then combining them all in a single concatenated Bitmap index is a viable option. It all depends. Understanding why it depends is of course important in making the correct decision with regard which way to go with Bitmap indexes …
For me, the biggest “selling point” for single-column bitmaps vs. concatenated bitmap indexes has always been the ability to combine them with OR, MINUS, etc. just as easily as with AND.
LikeLike
Hi Flado
Indeed, flexibility usually wins out. However, if you know that both columns A and B will always be used concurrently in AND predicates, then having them in a single bitmap index is worth considering.
LikeLike