Oracle的物化视图是包括一个查询结果的数据库对像,它是远程数据的的本地副本,或者用来生成基于数据表求和的汇总表。
测试物化视图的刷新,参考物化视图日志,一个源表对应多个物化视图刷新。
物化视图是实体表,是物理真实存在的(与View区别),占用存储空间的,可以创建索引,可以使用分区表。
按主键刷新,主键userid 。
create table TEST_MV_MASTER
(
userid VARCHAR2(32) not null,
name VARCHAR2(8),
birthdate DATE,
createdate DATE default sysdate,
score1 INTEGER,
score2 INTEGER
);
-- 增加主键
alter table test_mv_master add constraint pk_userid primary key (userid);
在源表上建物化视图日志,作 insert update delete 数据变更的记录。
物化视图有两种:默认是通过主键,另一种是通过ROWID,创建物化视图是需要有 WITH ROWID 子句,根据主键或者ROWID更新数据。
SQL> create materialized view log on test_mv_master ;
Materialized view log created
Executed in 0.208 seconds
测试脚本,insert delete update 三类数据变更的操作。
declare
i integer;
begin
-- 准备三类变化数据,insert update delete 三类
for i in 0..50 loop
insert into test_mv_master
values
(sys_guid(),
dbms_random.string('u', 8),
to_date(2451545 + trunc(DBMS_RANDOM.VALUE(0, 365 * 3)), 'J'),
sysdate,
abs(mod(dbms_random.random, 100)),
abs(mod(dbms_random.random, 100)));
end loop;
commit;
update test_mv_master t set t.score1 = t.score1 + 20 where t.score1<20;
delete test_mv_master t where t.score2 < 20;
commit;
end;
/
物化视图有两种:默认是通过主键,另一种是通过ROWID,创建物化视图是需要有 WITH ROWID 子句。即根据主键或者ROWID更新数据。
本例通过主键更新物化视图。
mv_source1 是test_mv_master全表的物化视图
create materialized view mv_source1
tablespace tb_crm
build deferred
refresh fast
disable query rewrite as
select *
from
test_mv_master;
mv_source2 是test_mv_master的条件物化视图
create materialized view mv_source2
tablespace tb_crm
build deferred
refresh fast
disable query rewrite as
select *
from
test_mv_master t where t.score1>= 60 and t.score2>=60;
物化视图创建完成后,第一次必须是全量刷新。否则提示错误:
ORA-12057: materialized view or zonemap “MV_SOURCE1” is invalid and must use complete refresh
SQL> EXEC DBMS_MVIEW.REFRESH(LIST =>'MV_SOURCE1',METHOD=>'C',PARALLELISM=>2);
PL/SQL procedure successfully completed
Executed in 0.311 seconds
SQL> EXEC DBMS_MVIEW.REFRESH(LIST =>'MV_SOURCE2',METHOD=>'C',PARALLELISM=>2);
PL/SQL procedure successfully completed
Executed in 0.268 seconds
SELECT * FROM MLOG$_TEST_MV_MASTER T;
当基本发生DML操作时,会记录到物化视图日志中,这时指定的时间4000年1月1日0时0分0秒。物化视图日志可以供多个物化视图使用,则一个物化视图刷新后会将它刷新的记录的时间更新为它刷新的时间。
INSERT为FE,DELETE为00,UPDATE为20 ,对第一列的更新为02,第二列为04,第二列和第三列都更新为0C。
执行数据脚本后,可以执行物化视图增量(快速)刷新 。
SQL> EXEC DBMS_MVIEW.REFRESH(LIST =>'MV_SOURCE1');
PL/SQL procedure successfully completed
Executed in 0.31 seconds
再次查询物化视图日志,刷新时间为当前时间:
SELECT * FROM MLOG$_TEST_MV_MASTER T;
SQL> EXEC DBMS_MVIEW.REFRESH(LIST =>'MV_SOURCE2');
PL/SQL procedure successfully completed
Executed in 0.349 seconds
再次查询物化视图日志,变更记录全部更新完毕,清空日志记录。
SELECT * FROM MLOG$_TEST_MV_MASTER T;
包括BUILD IMMEDIATE和BUILD DEFERRED两种。
BUILD IMMEDIATE是在创建物化视图的时候就生成数据。默认为BUILD IMMEDIATE。
BUILD DEFERRED则在创建时不生成数据,以后根据需要在生成数据。
包括ENABLE QUERY REWRITE和DISABLE QUERY REWRITE两种。
分别指出创建的物化视图是否支持查询重写。
查询重写是指当对物化视图的基表进行查询时,oracle会自动判断能否通过查询物化视图来得到结果,如果可以,则避免了聚集或连接操作,而直接从已经计算好的物化视图中读取数据。默认为DISABLEQUERY REWRITE。
指当基表发生了DML操作后,物化视图何时采用哪种方式和基表进行同步。刷新的模式有两种:ON DEMAND和ON COMMIT。
ON DEMAND和ON COMMIT物化视图的区别在于其刷新方法的不同,ON DEMAND指物化视图在用户需要的时候进行刷新,可以手工通过DBMS_MVIEW.REFRESH等方法来进行刷新,也可以通过JOB定时进行刷新,即更新物化视图,以保证和基表数据的一致性。
ON COMMIT是指,一旦基表有了COMMIT,即事务提交,则立刻刷新,立刻更新物化视图,使得数据和基表一致。对基表,平常的COMMIT在0.01秒内可以完成,但在有了ON COMMIT视图后,居然要6秒。速度减低了很多倍。ON COMMIT视图对基表的影响可见一斑。
注意:设置REFRESH ON COMMIT的物化视图不能访问远端对象。
物化视图有三种刷新方式:COMPLETE、FAST和 FORCE。
完全刷新(COMPLETE),会删除表中所有的记录(如果是单表刷新,可能会采用TRUNCATE的方式),然后根据物化视图中查询语句的定义重新生成物化视图。
快速刷新(FAST),采用增量刷新的机制,只将自上次刷新以后对基表进行的所有操作刷新到物化视图中去。FAST必须创建基于主表的视图日志。对于增量刷新选项,如果在子查询中存在分析函数,则物化视图不起作用。
强制刷新(FORCE),Oracle会自动判断是否满足快速刷新的条件,如果满足则进行快速刷新,否则进行完全刷新。
Oracle物化视图的快速刷新机制是通过物化视图日志完成的。Oracle通过一个物化视图日志还可以支持多个物化视图的快速刷新。
物化视图日志根据不同物化视图的快速刷新的需要,可以建立为ROWID或PRIMARY KEY类型的。还可以选择是否包括SEQUENCE、INCLUDING NEW VALUES以及指定列的列表。
物化视图日志的名称为MLOG$_后面跟源表的名称。
物化视图都会包括的4列状态数据:
SNAPTIME$$:用于表示刷新时间。
DMLTYPE$$:用于表示DML操作类型,I表示INSERT,D表示DELETE,U表示UPDATE。
OLD_NEW$$:用于表示这个值是新值还是旧值。N(EW)表示新值,O(LD)表示旧值,U表示UPDATE操作。
CHANGE_VECTOR$$:表示修改矢量,用来表示被修改的是哪个或哪几个字段。
如果WITH后面用ROWID,则物化视图日志中会包含:M_ROW
建立快速刷新的两个物化视图来演示时间列的变化。只有建立快速刷新的物化视图才能使用物化视图日志,如果只建立一个物化视图,则物化视图刷新完会将物化视图日志清除掉。如果一个源表对应多个物化视图,需要所有物化视图都刷新完成,才能将物化视图日志清除。
用户下物化视图的信息,包括物化视图名称,更新方式,使用的数据链路名称,更新的时间 。
可以查询源表对应的物化视图名称,使用到源表的字段名以及顺序。
select * from user_mview_keys t order by t.mview_name,t.position_in_select ;