刷新组的基本概念
(本部分内容基本翻译自:Materialized View Concepts and Architecture,有问题请移步原文。)
什么是刷新组
通常我们创建的MView会不止一个,而且各个MView的Master Table之间是有约束,数据一致性关联的,如果我们对各个MView分开刷新的话我们是不能保证关联数据的完整性和事务的一致性的。Oracle提供了刷新组来解决这个问题。在刷新组刷新之后Oracle可以保证在刷新组里面的所有的表在刷新的那个时间点的是一致的。
刷新组的大小
Oracle专门针对大的MView刷新组做了优化,也就是说对于相同数量的MView来说一个大的刷新组要多个小的刷新组刷新的要快,即刷新的一个含有100个MView的刷新组要比刷新5个各含有20个MView的刷新组要快。
但是速度不是唯一的需要注意的问题,再决定一个刷新组大小的时候我们还需要考虑下面的这些问题:
-
数据的一致性
- 就像我们上面所说的,数据的完整性和事物的一致性是我们最需要考虑的问题,考虑大小之前先保证一致性。 表锁
- 再刷新组的刷新期间,所有的在组里面的表会被锁住而不让别的程序进行更新的操作,因为表的更新会破坏数据的一致性。这样就造成刷新组越大,表被锁的时间也就越长。因此针对这个来说越小的刷新组是越有利的。 网络的稳定性
- 如果在一个刷新组刷新完成之前网络终端的话将会导致整个组的刷新回滚,因此在网络不好的时候越大的刷新组是越不利的,我们需要根据网络的状况来调整我们的刷新组的大小。
下面总结一下:
大刷新组的优点 | 小刷新组的优点 |
---|---|
相比较多个小的刷新组来说大的刷新组刷新速度要更快些 | MView被锁住的时间要短些 |
一次刷新命令就能够把组里面的MView全部刷新 | 网络条件不好的时候可能会导致整个组刷新的回滚,浪费时间 |
刷新组的基本操作
说完了刷新组的概念之后,接下来我们来进行下实际的演练。Oracle使用DBMS_REFRESH包来进行刷新组的创建和管理操作,下面我们一个个说明下。
建立刷新组
我们可以使用DBMS_REFRESH.MAKE来创建一个刷新组,具体语法请移步MAKE Procedure。
下面为我们前面建立的MView创建一个名为TEST_GROUP的刷新组,这个刷新组将每15分钟做一次刷新。
USER @ orcl > begin DBMS_REFRESH . MAKE (
2 name => ' USER.TEST_GROUP ' , - 刷新组的名称
3 list => '' , - 刷新组所包含的 MView List ,我们先不添加这个
4 next_date => SYSDATE , - 下次刷新的时间
5 interval => ' SYSDATE+(15/(24*60)) ' - 刷新的时间间隔,这个 Oracle 是自动计算的,这里填写的是下下次刷新时间
6 ) ;
7 end ;
8 /
PL / SQL procedure successfully completed .
接下来要介绍的是DBMS_REFRESH.ADD方法,具体语法见ADD Procedure。下面我们将前面建立的MView MVT加入到刷新组里面
2 name => ' TEST_GROUP ' ,
3 list => ' USER.MVT '
4 ) ;
5 end ;
6 /
PL / SQL procedure successfully completed .
步骤很是简单,下面我们来检验一下成果,我们可以通过DBA_REFRESH_CHILDREN来查询刷新以及各个刷新组所包含的MView的信息。也可以使用DBA_REFRESH来之查询刷新组的信息。
USER @ orcl > col name for a15
USER @ orcl > col rowner a15
USER @ orcl > col rowner for a15
USER @ orcl > col rname for a15
-- 查询刷新组及相关MView的信息
USER @ orcl > select owner , name , rowner , rname , job from dba_refresh_children ;
OWNER NAME ROWNER RNAME JOB
-------- -- --------------- --------------- --------------- ----------
USER MVT USER TEST_GROUP 45
-- 只查询刷新组的信息
USER @ orcl > select rowner , rname , job , next_date , interval from dba_refresh ;
ROWNER RNAME JOB NEXT_DATE INTERVAL
------------- -- --------------- ---- ------------------- --------------------
USER TEST_GROUP 46 2009 - 04 - 25 10 : 05 : 01 SYSDATE + ( 15 / ( 24 * 60 ))
USER TEST_GROUP2 47 2009 - 04 - 25 10 : 05 : 28 SYSDATE + ( 15 / ( 24 * 60 ))
这上面的查询结果我们能看到我们所增加的刷新组TEST_GROUP以及组里面存在的MView MVT。
细心的人可能注意到了上面我的结果里面有一列是JOB,这列里面包含的就是这个刷新组所对应的JOB的jobid,这个jobid是怎么来的呢?还记得在前面我们创建刷新组的时候曾经设定了一个参数inverval么,创建刷新组的时候Oralce会自动根据你的设置来在系统中创建一个JOB,就是现在我们能看到的了,下面我们把这个JOB的详细信息查询出来看看。
USER @ orcl > col priv_user for a15
USER @ orcl > col schema_user for a15
USER @ orcl > col what for a70
USER @ orcl > col interval for a20
USER @ orcl > select job , priv_user , schema_user , interval , what from dba_jobs where job = 45 ;
JOB PRIV_USER SCHEMA_USE INTERVAL WHAT
-- -- ---------- ---------- -------------------- -----------------------------------------------
45 USER USER SYSDATE + ( 15 / ( 24 * 60 )) dbms_refresh . refresh ( ' "USER"."TEST_GROUP" ' ) ;
列WHAT里面的内容就是我们要引入的DBMS_REFRESH的另一个方法REFRESH了,调用DBMS_REFRESH.REFRESH对整个组进行手工的刷新操作,详细语法REFRESH Procedure。这个过程用法也是很简单,这里就不再细说了。
维护刷新组
下面说下DBMS_REFRESH的另外三个方法,分别是CHANGE, SUBTRACT和DESTROY。
-
CHANGE Procedure
- 改变刷新组的刷新频率。 DESTROY Procedure
- 删除刷新组里面所有的MView并将刷新组删除。 SUBTRACT Procedure
- 从刷新组里面删除指定的MView。
用法也是很简单,就演示下它们的用法:
USER @ orcl > begin DBMS_REFRESH . CHANGE (
2 name => ' TEST_GROUP ' ,
3 next_date => sysdate ,
4 interval => sysdate + ( 30 / ( 24 * 60 ))
5 ) ;
end ;
7 /
PL / SQL procedure successfully completed .
-- 看看修改之后的结果
USER @ orcl > select job , priv_user , schema_user , interval , what from dba_jobs where job = 45 ;
JOB PRIV_USER SCHEMA_USE INTERVAL WHAT
-- -- ---------- ---------- -------------------- ----------------------------------------------------------------------
45 USER USER 2009 - 04 - 25 07 : 39 : 48 dbms_refresh . refresh ( ' "USER"."TEST_GROUP" ' ) ;
-- 把我们刚刚建立的TEST_GROUP删除掉
USER @ orcl > exec dbms_refresh . destroy ( ' USER.TEST_GROUP ' ) ;
PL / SQL procedure successfully completed .
-- 这时已经找不到这个刷新组了
USER @ orcl > select * from dba_refresh_children ;
no rows selected
-- 再看看我们的job也已经消失了
USER @ orcl > select job , priv_user , schema_user , interval , what from dba_jobs where job = 45 ;
no rows selected