Materialized Views
Materialized view (MV) have properties of both persistent table and view.
It is defined similar to a view and its source query is used by the engine to
populate underlying MV table with data rows. It is not allowed to modify
materialize view data using DML statements. The only way to update MV content
is to run special new REFRESH statement (see below). Like a regular table,
MV can have indices of any kind. Unlike tables, it is not allowed to create
constraints and triggers for MV.
Syntax
Create, alter and drop
CREATE [OR ALTER] MATERIALIZED VIEW <view_name> [(columns_names)]
AS <query>
[WITH [NO] DATA]
ALTER MATERIALIZED VIEW <view_name> [(columns_names)]
AS <query>
[WITH [NO] DATA]
Creates new or modifies existing MV using specified query and optional list of
column names. Optional WITH DATA clause specify that MV should be filled with
data immediately after creation (altering). When WITH NO DATA specified, or
when this clause is omitted, MV is not populated with data and remains empty.
ALTER also drops all existing indices of MV. If regular (i.e. not materialized)
view with the same name exists, error is raised.
RECREATE MATERIALIZED VIEW <view_name> [(columns_names)]
AS <query>
[WITH [NO] DATA]
Drops materialized or regular view, if it exists, and creates a new materialized view.
There is no separate command to drop MV, use regular DROP VIEW statement to do it.
Special commands
ALTER MATERIALIZED VIEW <view_name> [(columns_names)]
AS <query>
TO NOT MATERIALIZED
Special kind of ALTER statement that converts materialized view into regular view with the same name. Dependend objects are not affected. All existing indices and data rows of former MV are dropped.
ALTER VIEW <view_name> [(columns_names)]
AS <query>
TO MATERIALIZED
Special kind of ALTER statement that converts regular view into materialized view with the same name. Dependend objects are not affected.
Refreshing data of materialized views
REFRESH MATERIALIZED VIEW [CONCURRENTLY|DROP DATA] [CASCADE]
Executes MV query and replaces MV data with query resultset. All MV indexes are updated correspondingly. This is DDL command and actual execution is deferred untill COMMIT of the current transaction. There are few forms of this command:
1. Full reload in exclusive mode:
REFRESH MATERIALIZED VIEW <view_name>
deactivates all active indices, deletes all existing data, fill MV table with
rows from MV query and activates all indices that was deactivated before.
This is the fastest way of refresh, if there have been many changes in tables that
makes up the MV query.
The exclusive reservation of MV table is required to ensure no other
connection attempts to query MV while it is being refreshed.
This approach is used also by CREATE [OR ALTER], ALTER and RECREATE statements
for initial data load.
Note: if any error happens during data load stage, then all newly loaded data will
be deleted, previously deactivated indices will be activated (as empty) and original
error will be reported to the user. I.e. MV table will be emptied and this can not
be undone even by rollback. It is expected that error reason will be fixed by user
(for example, by correcting MV query) and REFRESH statement will be repeated again.
Note: if error(s) happens when activating some index(es) (after data load stage),
than this index(es) will be left in inactive state. Such error(s) will not affect
already loaded data nor other indices. Transaction commit will succeed and index
build errors will be put into status-vector as warnings. Such indices could be
activated later using regular ALTER INDEX <index_name> ACTIVE statements, if
necessary.
2. Update only changed rows in shared mode:
REFRESH MATERIALIZED VIEW <view_name> CONCURRENTLY
This second form doesn’t require exclusive reservation and allows concurrent connections to run statements referencing MV while it is refreshed. In this case, engine creates two ordered cursors for MV table data and for MV query resultset. Then merge algorithm is used to update changed rows, insert new rows and delete rows that not exists anymore. All changes of MV rows are made under transaction control therefore it provides safe and consistent concurrent access of the MV table. Both cursors are ordered basing on columns list of unique index.
Unique index must be built on the MV to allow this algorithm to work.
Also, view query text stored in RDB$VIEW_SOURCE column should not be nullified
as it is used by the engine to create internal merge statement.
This form of REFRESH statement should be preferred over first one when concurrent
access is required or when there was not much changes in the tables of the MV query
since previous refresh.
Note: if MV query contains ORDER BY clause, the natural order of rows can be
changed after concurrent refresh and not satisfy ORDER BY clause anymore.
3. Delete all data (exclusive mode):
REFRESH MATERIALIZED VIEW <view_name> DROP DATA
This statement deletes data from MV table and indices. It is useful when DBA needs
to free space occupied by MV data and indices. EX lock is required as in the first
form of REFRESH statement.
4. Cascading refresh
Use optional clause CASCADE to refresh all materialized views that given MV
depends on. The refresh order ensures that each MV is handled once and only
after all MVs it depends on.
- Using
CONCURRENTLYwithCASCADErequires that all MVs to refresh must have unique index, else error will be raised. - Using
DROP DATAwithCASCADEwill delete data of all affected MVs. - The statement put warning with name of each MV that will be handled into status-vector. It allows to know in advance (before commit) list and order of affected MVs.
gbak support
gbak backup requires no special support. Data of materialized view doesn’t go into backup file - same as for regular views.
gbak restore refreshes all materialized views at the very end of restore process. MV’s are refreshed in correct order, taking into account their dependencies on each other (see cascading refresh).
There is new command-line switch to make gbak not refresh MV’s : -NO_MATVIEWS.
It could be shortened up to 4 initial letters: -NO_M.
Corresponding option in Services API for isc_action_svc_restore action is
isc_spb_res_no_matviews.
Note: backup with materialized view(s) can’t be restored with Firebird version that
doesn’t supports MV’s. To migrate onto such Firebird version, use ALTER MATERIALIZED
VIEW ... TO NOT MATERIALIZED statement before backup. This might be improved later.
Video and presentation
Webinar walkthrough of materialized views in Firebird / HQbird:
Presentation (PDF): Materialized Views in Firebird