全部博文(389)
分类: Oracle
2014-02-15 15:44:32
MV的Synchronous Reresh
传统的fast refresh通过在base表上增加一个触发器,当对表进行dml操作时,同时也有相关的记录
被insert到mv log表里。当mv以on commit模式定义时,在对mv的更新同时也对mv同时进行了更新,这样
的好处是mv和base的数据实时保持一致,但是对事务的响应时间形成很重要的影响.
在12C中oracle针对DW的环境引入了一种全新的刷新模式称为synchronous refresh(下文简称synch refresh)。
synchronous的主要的思想是时同时更新base和mv,这也是synchronous的名称来源。
synch refresh使的场景有以下特定的假设.一般认为在从外部加载数据到DW中表的时候,会经过清洗,合规
检查等等。首先会把外部的数据加载到一个中间表(有时候也称为staging area),在进行了相应的处理后,然后
再加载到DW的相应的表,一般是通过exchange partition操作.
synch refresh要求基表必须是range分区或复分分区且顶层分区是以range方式进行分区,必须要主键。其
mv的分区方式和表一致.synch refresh也有类似fash refresh一样的mv log,不过称为staging log.在fash
refresh的mv log中的数据由oracle中的trigger进行填充,而staging log由人工去填充,充当的角色相当于
DW数据表中的staging area。
来看一个例子.假设有表t1,根据字段a,以range分区,且a是primary key
SQL> create table t1
2 (a int,
3 b int)
4 partition by range(a)
5 (partition p0 values less than (10),
6 partition p1 values less than (20),
7 partition p2 values less than (30));
Table created.
SQL> alter table t1 add primary key (a)
Table altered.
在表t1上创建staging log,指定st_t1为staging log的表名
SQL> create materialized view log on t1 for synchronous refresh using st_t1;
Materialized view log created.
创建mv
SQL> create materialized view mv_t1
2 partition by range(a)
3 (partition p0 values less than (10),
4 partition p1 values less than (20),
5 partition p2 values less than (30))
6 REFRESH USING TRUSTED CONSTRAINTS
7 as
8 select a,sum(b) from t1 group by a;
Materialized view created.
sum(b)和直接select b没有区别,因为a是主健,这里仅是例子
SQL> select * from t1;
no rows selected
SQL> select * from mv_t1;
no rows selected
现在已经建好和mv,但是都没有数据.不过还需要把mv注册成sync refresh的方式,对于sync refresh
oracle提供了一个全新的dbms_sync_refresh包用来执行相关的操作
SQL> execute dbms_sync_refresh.register_mviews('MV_T1');
PL/SQL procedure successfully completed.
接下来需要做是的直接对st_t1表进行insert数据,这一步相当于在DW的数据加载到staging area的阶段。
只是数据已经被insert到st_t1表中了,而不是原来自定义的专用表
SQL> insert into st_t1(dmltype$$,a,b) values('I',15,1);
SQL> insert into st_t1(dmltype$$,a,b) values('I',5,1);
SQL> insert into st_t1(dmltype$$,a,b) values('I',25,1);
SQL> commit;
准备staging_log和刷新mv
SQL> exec dbms_sync_refresh.prepare_staging_log('C##FRANK','T1');
PL/SQL procedure successfully completed.
SQL> exec dbms_sync_refresh.prepare_refresh(dbms_sync_refresh.get_group_id('MV_T1'));
PL/SQL procedure successfully completed.
刷新mv
SQL> exec dbms_sync_refresh.execute_refresh(dbms_sync_refresh.get_group_id('MV_T1'));
PL/SQL procedure successfully completed.
现在再看两个表的数据
SQL> select * from t1;
A B
---------- ----------
5 1
15 1
25 1
SQL> select * from mv_t1;
A SUM(B)
---------- ----------
5 1
15 1
25 1
可以看到mv中的数据和base表中的数据一致的,其实质是两者都是通过exchange partition操作来形成最新的数据。
通过sync refresh主要的好处是在加载到DW中表的时候,同时也通过exchange partition更新了mv的数据,相比fast
refresh在计算后通过merge迁移到mv中的方式要快得多,不好的地方是使用场景有限,其他还有一些限制,具体可以
参考相关的oracle data warehousing guide.