12c 物化视图 - 刷新方式的对比
1. 完全刷新
完全刷新的特点是将主表上的查询结果全部写入和物化视图同名的基表中。当再次刷新时,先清空基表中的所有数据,再加载最新执行的查询结果。
使用关键字refresh complete创建完全刷新物化视图
create materialized view mvc_costs
refresh complete on demand
as select promo_id,sum(unit_cost) cost from costs group by promo_id;
手工执行完全刷新命令,完全刷新的字母为C
exec dbms_mview.refresh('MVC_COSTS','C');
如果创建的物化视图视图中包含大量数据,可以使用关键字build deferred不加载数据,等数据库不忙的时候在手工执行完全刷新的方式。
create materialized view mvn_costs
tablespace users
build deferred
refresh complete on demand
as select promo_id,sum(unit_cost) cost from costs group by promo_id;
2. 快速刷新
快速刷新也可以理解为增量刷新。增量数据由物化视图日志来管理。物化视图创建成功后,查询结果已经保存在物化视图的同名基表中。当主表产生DML操作时视图日志会将其保存到增量基表中,等到执行快速刷新时将这部分数据同步到物化视图基表中,并清除自身的数据。
快速刷新物化视图需要创建日志
create materialized view log on costs with rowid,
sequence(promo_id,unit_cost) including new values;
使用关键字refresh fast创建快速刷新的物化视图
create materialized view mvf_costs
segment creation immediate
refresh fast with rowid on demand
as select promo_id,sum(unit_cost) cost from costs group by promo_id;
手工执行完全刷新命令,完全刷新的字母为F
exec dbms_mview.refresh('MVF_COSTS','F');
3. 提交时刷新
刷新是一种触发条件,可以手工触发,也可以自动触发。所谓手工触发就是执行dbms_mview.refresh包来触发刷新事件。在应用程序中不一定需要人为的执行这条命令,而是当程序中满足某些条件后向数据库发去这个命令来完成刷新。另一种触发方式是自动刷新。当主表DML操作提交后就触发刷新事件,从而达到主表和物化视图实时同步的效果。这种方式有些像stream、Oracle GodenGate、或者是DataGuard的逻辑复制。
提交刷新用起来很酷,但是也有需要注意的地方
1. 主表提交时基表也提交,系统开销增大。在繁忙的OLTP系统中会影响一部分性能。如果物化视图更新出错,主表也无法提交事务。
2. 主表和物化视图必须在同一个数据库中
3. 无法在基表上执行分布式事务
4. 不支持含有对象类型或Oracle补充支持类型的物化视图
下面看看提交时刷新物化视图的创建方法
create materialized view log on costs with rowid;
create materialized view mvfc_costs
refresh on commit
as select promo_id,sum(unit_cost) cost from costs group by promo_id
查看当前物化视图中的数据
select * from mvfc_costs;
PROMO_ID COST
---------- ----------
999 9313900.88
350 242949.08
351 258268
像主表添加2000条数据
insert into costs select * from costs where rownum<2001
2000 rows created.
SH@pdb1 > commit;
Commit complete.
再次查看物化视图数据已经变化,刷新成功
SH@pdb1 > select * from mvfc_costs;
PROMO_ID COST
---------- ----------
999 9607463.83
350 242949.08
351 258268
4. 从不刷新
看上去像个没用的东西,但是存在就有存在的道理。当我们需要保存一份快照,正好用的这个功能。当然通过create table as select的方式也可以实现,物化视图的灵活的地方是可以快照,也可以解除快照变为可刷新的物化视图。
来看看例子:
create materialized view mvs_costs
never refresh
as select promo_id,sum(unit_cost) cost from costs group by promo_id
查看视图描述信息
select mview_name,refresh_method,refresh_mode,build_mode,fast_refreshable
from user_mviews
where mview_name='MVS_COSTS'
MVIEW_NAME REFRESH_ REFRES BUILD_MOD FAST_REFRESHABLE
-------------------- -------- ------ --------- ------------------
MVS_COSTS NEVER NEVER IMMEDIATE DIRLOAD_LIMITEDDML
使用下面的sql语句可以将从不刷新的物化视图改变为完全刷新方式
SH@pdb1 >
alter materialized view mvs_costs
refresh on demand complete;
Materialized view altered.
状态从never修改为complete
SH@pdb1 >
select mview_name,refresh_method,refresh_mode,build_mode,fast_refreshable
from user_mviews
where mview_name='MVS_COSTS';
MVIEW_NAME REFRESH_ REFRES BUILD_MOD FAST_REFRESHABLE
-------------------- -------- ------ --------- ------------------
MVS_COSTS COMPLETE DEMAND IMMEDIATE DIRLOAD_LIMITEDDML
横向对比各种物化视图的刷新方式会发现有些先进、有些落后。其实不是这样的,每个功能都有适合它的使用场景。最适合的才是最好的。