| Lesson 5 | Index a materialized view |
| Objective | Describe the conditions and types of indexing for materialized views. |
A materialized view is a physical table that stores the results of a query. Because it is a real segment on disk, you can (and usually should) create indexes on it, just as you would on a base table.
Indexing a materialized view is not just about speeding up queries. The right indexes also support:
This lesson explains when to index a materialized view, which index types to consider, and how those choices interact with refresh options in current Oracle Database releases (11gR2+, 19c, 23c).
You generally add indexes to a materialized view under three conditions:
product_id, sales_month, or region_id,
those columns are strong candidates for B-tree indexes.
ENABLE QUERY REWRITE is used, the optimizer is more likely to choose the materialized view if it
can see cheap index-based access paths for common query patterns.
If the materialized view is small, rarely queried, or refreshed very frequently, you may choose fewer or even no indexes to minimize refresh overhead.
B-tree indexes are the standard indexing option and are the safest default for materialized views. They are appropriate when:
WHERE predicates, joins, or ORDER BY clausesTypical B-tree indexes on a summary materialized view include:
product_id, sales_month)region_id, channel_id)Bitmap indexes are often used on materialized views in read-mostly data warehouses when:
Bitmap indexes can greatly accelerate star-schema style queries but are not recommended on materialized views with heavy concurrent DML or very frequent refreshes, because updates to bitmap keys can lock many rows and increase contention.
Materialized views often include expressions, for example:
TRUNC(sales_date, 'MM') as a month keyIf your queries filter on the same expressions, a function-based index on the materialized view is appropriate:
CREATE INDEX mv_sales_month_ix
ON mv_sales_summary (TRUNC(sales_date, 'MM'));
This avoids recalculating the function for every row at query time and gives the optimizer a direct index path on the expression.
In modern Oracle data warehouses, materialized views are frequently partitioned (for example, by month or day). In this case:
FAST refresh uses materialized view logs on the base tables to send only changed rows to the materialized view. Oracle then needs an efficient way to find the corresponding row(s) inside the materialized view.
GROUP BY columns in summary views.
For a typical aggregate materialized view, you will define a concatenated B-tree index on the summary key, for example:
CREATE UNIQUE INDEX sales_mv_pk
ON sales_summary_mv (product_id, sales_month);
This index serves two purposes:
Indexing and refresh strategy are closely related. A simplified version of the REFRESH clause in
CREATE MATERIALIZED VIEW looks like this:
REFRESH { FAST | COMPLETE | FORCE }
ON { DEMAND | COMMIT }
DBMS_MVIEW.REFRESH), often during a batch window; you can afford heavier indexing here than with
ON COMMIT.
Rule of thumb: the more often you refresh, the more cautious you should be about adding “nice-to-have” indexes that are not absolutely necessary for query or refresh performance.
The following example shows a simple monthly sales summary and a reasonable indexing strategy:
-- Base fact table: SALES_FACT
-- Columns: sales_date, product_id, region_id, sales_amount
CREATE MATERIALIZED VIEW sales_monthly_mv
BUILD IMMEDIATE
REFRESH FAST ON COMMIT
ENABLE QUERY REWRITE
AS
SELECT
product_id,
TRUNC(sales_date, 'MM') AS sales_month,
SUM(sales_amount) AS total_sales,
COUNT(*) AS txn_count
FROM sales_fact
GROUP BY
product_id,
TRUNC(sales_date, 'MM');
-- Index to support fast refresh and common queries
CREATE UNIQUE INDEX sales_monthly_mv_pk
ON sales_monthly_mv (product_id, sales_month);
-- Optional: function-based index to support date-based filters
-- (if you often filter directly on TRUNC(sales_date, 'MM'))
In this case:
UNIQUE index on (product_id, sales_month) supports both fast refresh
and analytic queries.Most modern performance-tuning and data-warehouse designs use read-only materialized views:
Updatable materialized views (part of multimaster replication configurations) are still supported but are less common. Every additional index on an updatable materialized view increases the cost of propagating changes and resolving conflicts. Unless you specifically need bidirectional replication, a read-only, well-indexed materialized view is the simpler and more robust design.
In the next lesson, you will learn how to handle materialized views that become invalid due to changes in the underlying tables.