物化视图定义
视图是一个虚拟表(也可以认为是一条语句),基于它创建时指定的查询语句返回的结果集,每次访问它都会导致这个查询语句被执行一次,为了避免每次访问都执行这个查询,可以将这个查询结果集存储到一个物化视图(也叫实体化视图)。
物化视图与普通视图相比的区别是物化视图是建立的副本,它类似于一张表,需要占用存储空间,对一个物化视图查询的执行效率与查询一个表是一样的。
物化视图的优点是查询速度快,因为数据已经存在,查询物化视图就等同于查询一张表的数据。
物化视图的缺点就是占用空间,因为数据是真实存储的,而不像普通视图只是一条查询语句。
物化视图创建语法:
sql
CREATE MATERIALIZED VIEW view_name
[BUILD IMMEDIATE | BUILD DEFERRED]
refresh [FAST|COMPLETE|FORCE]
[ON [COMMIT|DEMAND] | START WITH (start_time) NEXT (next_time)]
AS
subquery
BUILD IMMEDIATE:是在创建物化视图的时候就生成数据。(默认)
BUILD DEFERRED:在创建时不生成数据,以后根据需要再生产数据。
刷新(refresh):指在基表发生了DML操作后,物化视图何时采用哪种方式和基表进行同步。
refresh关键字后面可以指定的刷新方式有三种:FAST、COMPLETE、FORCE(默认),FAST刷新采用增量刷新,只刷新自上次刷新以后进行的修改。COMPLETE刷新对整个物化视图进行完全的刷新。如果选择FORCE方式,则oracle在刷新时会去判断是否可以进行快速刷新,如果可以则采用FAST方式,否则采用COMPLETE的方式。
刷新的模式有两种:ON COMMIT和ON DEMAND(默认),ON COMMIT指基表发生COMMIT操作时自动刷新;ON DEMAND指需要手动刷新物化视图。
下面的实例都是基于oracle中scott用户自带的emp表和dept表数据进行操作:
类型一:手动刷新的物化视图
创建物化视图:
sql
create materialized view MV_EMP
refresh force on demand
as
select e.ename,d.dname from emp e
left join dept d on e.deptno = d.deptno;
以上创建的含义就是创建一个名称为mv_emp的物化视图,视图数据的采用手动刷新的模式(on demand),自动选择增量或全量更新(refresh force)。
创建完成后,可以发现,在PL/SQL中,Tables和Materialized views中,都会显示刚才创建的物化视图对象。
查询物化视图数据:
往emp表中插入一条数据(15条记录):
查询物化视图数据(14条记录):
可以看到物化视图结果集中只有14条记录,最新插入的记录并没有被查询出来,这时因为刚才创建的物化视图是手动刷新模块(on demand),所以需要手动执行物化视图数据更新语句,进行数据更新操作。
手动刷新物化视图记录:
sql
begin
dbms_mview.refresh('mv_emp');
end;
刷新后,再查询物化视图(15条记录):
这次数据跟emp表记录数一致了。
类型二:自动刷新的物化视图
sql
create materialized view mv_emp1
refresh force on commit
as
select e.ename,d.dname from emp e, dept d where e.deptno = d.deptno;
以上创建的含义就是创建一个名称为mv_emp1的物化视图,视图数据的采用自动刷新的模式(on commit),自动选择增量或全量更新(refresh force)。
这里需要注意下,emp表和dept表关联的写法改了,以为如果使用left join关键字,会提示"无法为实体化视图设置 ON COMMIT 刷新属性"。
视图创建完毕,对视图进行查询(15条记录):
对emp表插入数据:
再查询物化视图:
发现物化视图的数据自动刷新了,跟emp表数据保持一致。
手动刷新和自动刷新两种刷新方式,根据实际情况进行选择,对数据实时性要求不高的,可以选择手动刷新,比如要做个每日报表,统计每天的数据情况,可以使用手动刷新(每天凌晨1点);对数据实时性要求高的,选择自动刷新。
类型三:创建时不生成数据的物化视图
sql
create materialized view mv_emp2
build deferred
refresh force on commit
as
select e.ename,d.dname from emp e, dept d where e.deptno = d.deptno;
类型一和类型二,视图创建完毕,视图就自动加载了基表的数据,如果要想在视图创建完毕后,先不生成数据,在需要的时候再生成数据,则可以使用build deferred关键字进行设置。
查询生成的视图:
可以看到视图中没有任何记录。
如果想让视图中加载数据,则需要手动执行下数据更新的方法:
sql
begin
dbms_mview.refresh('mv_emp2');
end;
执行完毕,再次查询,视图中就加载了最新的数据:
此时因为视图是提交时更新,所以在emp表数据变化时时,视图的数据会随之更新。
类型四:创建增量更新的物化视图
注意:创建增量刷新的物化视图,必须:
1.创建物化视图中涉及表的物化视图日志,记录基表发生了什么变化,用这些记录去更新物化视图。
2.在查询语句中,必须包含所有表的rowid(以rowid方式建立物化视图日志)
sql
--为基表创建 物化视图日志
create materialized view log on emp with rowid;
create materialized view log on dept with rowid;
执行完毕后,在Tables中可以看到创建的日志表:
创建增量更新的物化视图,查询语句中必须加上基表的rowid
sql
create materialized view mv_emp3
refresh fast on demand
as
select e.rowid erowid,d.rowid drowid, e.ename,d.dname
from emp e, dept d where e.deptno = d.deptno;
以上创建的含义就是创建一个名称为mv_emp3的物化视图,视图数据的采用手动刷新的模式(on demand),增量更新(refresh fast)。
查询视图数据集:
对emp表删除一条数据,查看物化视图日志表中数据的信息:
手动进行刷新操作:
sql
begin
dbms_mview.refresh('mv_emp3');
end;
物化视图的数据才会被更新,同步物化视图日志的数据被被清除,也就是说物化视图日志中的数据是待处理的数据,当物化视图更新后,物化视图日志中的数据就会被删除。