Bitmap IndexesWhen they are brilliant, when they are dangerous, and how to use them correctly in Oracle
Bitmap indexes are one of the most misunderstood indexing features in Oracle. People hear “good for low-cardinality columns” and stop there. In reality, bitmap indexes are about more than cardinality: they are about workload shape, concurrency, join patterns, query combinations, storage behavior, partitioning rules, and the optimizer’s ability to combine bitmaps efficiently before converting them back to rowids.
What a bitmap index actually is
A B-tree index stores keys with row location references one entry at a time. A bitmap index stores the row locations for each distinct key value as a bitmap. Conceptually, each distinct value owns a string of bits; a bit is set when the corresponding row contains that value. Oracle documents this internal model directly in the SQL language reference and concepts materials. A bitmap index is therefore not just “another index type” - it is a different access representation optimized for combining many predicates efficiently in read-heavy workloads.
Bitmap indexes are strongest when the database can answer a query by combining several low-cardinality predicates with bitmap operations such as BITMAP AND, BITMAP OR, and BITMAP MERGE before touching the table rows.
Why bitmap indexes work so well in reporting and warehousing
Oracle’s documentation repeatedly positions bitmap indexes as a data warehousing feature because they are suited to low-concurrency, read-heavy environments. Their biggest advantage is that the optimizer can combine multiple bitmap indexes very efficiently, which is especially useful when users ask ad hoc questions with several equality predicates. Oracle also documents execution plan operators such as BITMAP AND, BITMAP OR, BITMAP MERGE, and BITMAP CONVERSION TO ROWIDS that show this process directly in plans.
Ad hoc filtering
Star queries
Compact storage
The optimizer does not have to pick one bitmap index and ignore the others. It can combine several, which is exactly why bitmap indexes age well in analytic SQL with many optional filters.
When bitmap indexes are the wrong choice
This is where many teams get into trouble. Oracle states clearly that bitmap indexes are not appropriate for applications with many concurrent transactions. The reason is locking behavior: a bitmap key can map to many rows, so updating a single row can lock a much larger bitmap entry range than you would see with a B-tree index. In heavy OLTP systems that means contention risk, not just slower maintenance.
Bad fit
- High-concurrency OLTP tables
- Frequent singleton INSERT/UPDATE/DELETE activity
- Columns whose usefulness is mainly range scans
- Workloads where locking side effects matter more than scan speed
Better fit
- Read-mostly reporting tables
- Fact tables in star schemas
- Batch-loaded or nightly-refreshed warehouse data
- Queries combining many equality predicates
It is true that low cardinality often points toward bitmap indexes, but Oracle’s own materials also show that concurrency and DML behavior are just as important. A technically low-cardinality column on a hot OLTP table is still a poor bitmap candidate.
How to read execution plans with bitmap operations
Once you know the plan operators, bitmap-index plans become much easier to reason about. Oracle’s plan language usually shows a sequence like bitmap single-value access, bitmap combination, and then a conversion to rowids before table access. If the query includes grouping or star transformations, the plan can become more complex, but these operators remain the main clues.
| Plan operator | Meaning | Why you care |
|---|---|---|
BITMAP INDEX SINGLE VALUE | Fetches a bitmap for one equality predicate | Shows Oracle is using the bitmap index directly for a specific value |
BITMAP AND | Intersects multiple bitmap vectors | Classic sign that several low-cardinality filters are being combined efficiently |
BITMAP OR | Unions multiple bitmap vectors | Useful when queries have alternative filter branches |
BITMAP MERGE | Merges bitmaps, often from range or more complex conditions | Helps explain more advanced bitmap processing |
BITMAP CONVERSION TO ROWIDS | Transforms the final bitmap into rowids | This is the bridge from bitmap filtering to actual row access |
EXPLAIN PLAN FOR SELECT product_category, SUM(sale_amount) FROM sales_fact WHERE region = 'WEST' AND order_status = 'COMPLETE' AND channel = 'ONLINE' GROUP BY product_category; SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
A representative bitmap plan usually includes one single-value bitmap access per indexed predicate, then BITMAP AND, then conversion to rowids. The exact cost, cardinality, and row counts vary by data and statistics, so the safe way to teach this is to focus on the operator pattern rather than inventing fixed numbers.
Designing single-table bitmap indexes well
The most common starting point is a single-table bitmap index on a fact or reporting table. Oracle’s SQL reference supports syntax such as CREATE BITMAP INDEX ... ON table(column), including local partitioned variants. For learners, the important design question is not simply “Is the column low cardinality?” but “Will users combine this column with other low-cardinality predicates often enough to justify the index?”
Strong candidates
Borderline candidates
Weak candidates
CREATE BITMAP INDEX bix_sales_region ON sales_fact(region); CREATE BITMAP INDEX bix_sales_status ON sales_fact(order_status); CREATE BITMAP INDEX bix_sales_channel ON sales_fact(channel);
SELECT owner, table_name, column_name, num_distinct, density, histogram FROM dba_tab_col_statistics WHERE owner = 'SH' AND table_name = 'SALES' ORDER BY num_distinct;
Use statistics as a clue, not a rigid threshold. Oracle’s own warehousing guidance emphasizes workload context more than a magical numeric cutoff.
Bitmap join indexes: one of the most powerful warehouse features
Bitmap join indexes extend the idea further: Oracle can index a fact table using values from joined dimension tables. This is particularly useful in star schemas because it can remove the need to visit some dimension tables during execution. Oracle’s SQL reference documents bitmap join index syntax with joins, and its warehousing guidance positions them as a performance feature for star-query environments.
CREATE BITMAP INDEX bix_sales_cust_country ON sales(c.country_id) FROM sales s, customers c WHERE s.cust_id = c.cust_id;
The key idea is subtle but important: the index belongs to the fact table, but its indexed attribute comes from the dimension table. That is why bitmap join indexes are a warehouse optimization rather than a generic OLTP tactic.
Bitmap join indexes are powerful, but they add maintenance complexity. They are best used where data refresh is controlled and query benefit is clear. They are not a casual default.
Partitioning, restrictions, and the rules that bite later
Oracle supports bitmap indexes on partitioned tables, including local bitmap indexes, but there are important restrictions around global partitioned bitmap indexes and around temporary tables. The SQL reference explicitly documents several of these constraints. If you work in warehouses, this matters because bitmap indexes and partitioning often appear together in the same design conversation.
| Topic | Practical takeaway | Why it matters |
|---|---|---|
| Local bitmap indexes | Common and natural on partitioned fact tables | Partition pruning plus bitmap combination can work very well together |
| Global partitioned bitmap indexes | Restricted by Oracle rules | You cannot assume every partitioning pattern is valid for bitmap indexes |
| Temporary tables | Bitmap indexes are not generally the right tool here | Warehouse-style read patterns, not transient OLTP staging, are the primary target |
| Heavy DML | Still a red flag even if the table is partitioned | Partitioning does not magically erase bitmap locking behavior |
CREATE BITMAP INDEX bix_sales_channel_local ON sales_fact(channel) LOCAL;
Practical design rules that hold up in real systems
There is no single cardinality percentage that decides everything, and Oracle’s own materials stop short of giving a magical threshold. That is good engineering discipline. Instead, use a set of practical questions.
Question 1
Question 2
Question 3
Question 4
If the table is warehouse-style, the predicates are mostly equality filters, the columns are low cardinality, and users combine several of them in ad hoc queries, bitmap indexes deserve strong consideration. If the table is OLTP-hot, they usually do not.
End-to-end demo: adding bitmap indexes to a reporting fact table
This demo stays close to what Oracle actually supports and to how DBAs really test bitmap indexes. Imagine a reporting schema with a fact table SALES_FACT loaded nightly. Users filter frequently by REGION, ORDER_STATUS, and CHANNEL. The goal is to check distinctness, create bitmap indexes on those attributes, validate the execution plan pattern, and compare the plan shape before and after.
This demo uses real Oracle syntax and real verification steps. It avoids invented elapsed times or fake cardinality outputs because those depend on data size, distribution, statistics, and hardware.
Step 1: inspect column statistics and gather stats if needed
SELECT column_name, num_distinct, histogram, density FROM user_tab_col_statistics WHERE table_name = 'SALES_FACT' AND column_name IN ('REGION', 'ORDER_STATUS', 'CHANNEL') ORDER BY column_name; -- If stats are stale, gather them before testing BEGIN DBMS_STATS.GATHER_TABLE_STATS( ownname => USER, tabname => 'SALES_FACT', cascade => TRUE, method_opt => 'FOR ALL COLUMNS SIZE AUTO'); END; /
The success condition here is not a specific number; it is that the candidate columns have relatively small NUM_DISTINCT values compared with the table size and that statistics are current enough for a fair plan test.
Step 2: capture the pre-index plan
EXPLAIN PLAN FOR SELECT channel, SUM(sale_amount) FROM sales_fact WHERE region = 'WEST' AND order_status = 'COMPLETE' AND channel = 'ONLINE' GROUP BY channel; SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
Before the bitmap indexes exist, the plan may show a full table scan or another access path. Record the operator pattern so you can compare it after the index creation.
Step 3: create the bitmap indexes
CREATE BITMAP INDEX bix_sales_fact_region ON sales_fact(region); CREATE BITMAP INDEX bix_sales_fact_status ON sales_fact(order_status); CREATE BITMAP INDEX bix_sales_fact_channel ON sales_fact(channel);
Step 4: verify the indexes exist and are bitmap indexes
SELECT index_name, index_type, table_name, status, visibility FROM user_indexes WHERE table_name = 'SALES_FACT' AND index_name IN ( 'BIX_SALES_FACT_REGION', 'BIX_SALES_FACT_STATUS', 'BIX_SALES_FACT_CHANNEL') ORDER BY index_name;
The success condition is straightforward: INDEX_TYPE should show BITMAP, and the indexes should be valid and usable.
Step 5: re-run the plan and look for bitmap operators
EXPLAIN PLAN FOR SELECT channel, SUM(sale_amount) FROM sales_fact WHERE region = 'WEST' AND order_status = 'COMPLETE' AND channel = 'ONLINE' GROUP BY channel; SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
What you are looking for here is not an invented cost value. You are looking for plan operators such as BITMAP INDEX SINGLE VALUE, BITMAP AND, and BITMAP CONVERSION TO ROWIDS. If those appear, Oracle is combining the bitmap indexes the way you intended.
Step 6: compare real execution with statistics
SELECT /*+ gather_plan_statistics */ channel, SUM(sale_amount) FROM sales_fact WHERE region = 'WEST' AND order_status = 'COMPLETE' AND channel = 'ONLINE' GROUP BY channel; SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));
This is the right place to validate whether the operator path is actually being used at runtime and whether row counts make sense. Again, the exact row and timing values depend on your data, so do not teach fake outputs here.
Step 7: prove why bitmap indexes are not for hot OLTP tables
The safest teaching approach is not to stage artificial lock contention numbers but to explain the rule clearly: if this same table were updated heavily by many concurrent sessions, the bitmap indexes could create contention that would be unacceptable in OLTP. Oracle’s documentation makes that design warning explicit.
A successful demo means the metadata verifies that the indexes are bitmap indexes, the plan shape changes in the expected bitmap-oriented way, and the test is done on a reporting-style table where bitmap locking behavior is not a hidden time bomb.
Knowledge check
These questions aim to sharpen decision-making, not just vocabulary. Read the explanations after you submit.
BITMAP AND. That operator is the classic signature that several bitmap filters are being combined before row access.
No comments:
Post a Comment