`

物化视图

阅读更多

       一、物化视图

       是一种特殊的物理表,“物化”(Materialized)视图是相对普通视图而言的。普通视图是虚拟表,应用的局限性大,任何对视图的查询,Oracle都实际上转换为视图SQL语句的查询。这样对整体查询性能的提高,并没有实质上的好处。

       物化视图的特点:
       (1) 物化视图在某种意义上说就是一个物理表(而且不仅仅是一个物理表),这通过其可以被user_tables查询出来。

       (2) 物化视图也是一种段(segment),所以其有自己的物理存储属性;
       (3) 物化视图会占用数据库磁盘空间,这点从user_segment的查询结果,可以得到佐证;

       二、物化视图的类型

       1ON DEMAND

       ON DEMAND顾名思义,仅在该物化视图“需要”被刷新,才进行刷新(REFRESH),即更新物化视图,以保证和基表数据的一致性;

       2ON COMMIT

       ON COMMIT物化视图的创建,和上面创建ON DEMAND的物化视图区别不大。因为ON DEMAND是默认的,所以ON COMMIT物化视图,需要再增加个参数即可。需要注意的是,无法在定义时仅指定ON COMMIT,还得附带个参数才行。创建ON COMMIT物化视图:

SQL> create materialized view mv_name refresh force on commit as select * from table_name;
备注:实际创建过程中,基表需要有主键约束,否则会报错(ORA-12014)。

       三、物化视图的刷新

       刷新的方法有四种:FAST、COMPLETE、FORCE和NEVER。

       FAST:采用增量刷新,只刷新自上次刷新以后进行的修改。

       COMPLETE:对整个物化视图进行完全的刷新。

       FORCE: Oracle在刷新时会去判断是否可以进行快速刷新,如果可以则采用FAST方式,否则采用COMPLETE的方式。

       NEVER:指物化视图不进行任何刷新。
       对于已经创建好的物化视图,可以修改其刷新方式,比如把物化视图mv_name的刷新方式修改为每天晚上10点刷新一次:
SQL> alter materialized view mv_name refresh force on demand start with sysdate next to_date(concat(to_char(sysdate+1,'dd-mm-yyyy'),' 22:00:00'),'dd-mm-yyyy hh24:mi:ss');


       四、ON DEMAND和ON COMMIT的区别

 

       前者不刷新(手工或自动)就不更新物化视图,而后者不刷新也会更新物化视图,只要基表发生了COMMIT。
       创建定时刷新的物化视图(指定物化视图每天刷新一次):
SQL> create materialized view mv_name refresh force on demand start with sysdate next sysdate+1;
上述创建的物化视图每天刷新,但是没有指定刷新时间,如果要指定刷新时间(比如每天晚上10:00定时刷新一次):
SQL> create materialized view mv_name refresh force on demand start with sysdate next to_date( concat( to_char( sysdate+1,'dd-mm-yyyy'),' 22:00:00'),'dd-mm-yyyy hh24:mi:ss');

        五、物化视图日志

        如果需要进行快速刷新,则需要建立物化视图日志。物化视图日志根据不同物化视图的快速刷新的需要,可以建立为ROWID或PRIMARY KEY类型的。还可以选择是否包括SEQUENCE、INCLUDING NEW VALUES以及指定列的列表。
可以指明ON PREBUILD TABLE语句将物化视图建立在一个已经存在的表上。这种情况下,物化视图和表必须同名。当删除物化视图时,不会删除同名的表。这种物化视图的查询重写要求参数QUERY_REWRITE_INTEGERITY必须设置为trusted或者stale_tolerated。

         简单试验在master site上创建表和mview log
SQL> create table stu (id varchar2(10) primary key ,name varchar2(20));
Table created.
SQL> create materialized view log on stu;
Materialized view log created.
mv site上创建mview
SQL> create materialized view stu_mv refresh fast start with sysdate next sysdate+1/1440 with primary key as select * from stu@to_vm9;
Materialized view created.
SQL> select job,log_user,last_date,last_sec,next_date,next_sec,interval,what from user_jobs;
JOB LOG_USER LAST_DATE   LAST_SEC  NEXT_DATE   NEXT_SEC   INTERVAL       WHAT                                       
--- --------- ----------- --------- ----------- ---------- -------------- -----------------------------------------
21 SEAGULL   2008-2-18 1 14:41:43  2008-2-18 1 14:42:43   sysdate+1/1440 dbms_refresh.refresh('"SEAGULL"."STU_MV"');
SQL> select * from tab;
TNAME                          TABTYPE  CLUSTERID
------------------------------ ------- ----------
STU_MV                         TABLE
master site上对master table做更新:
SQL> INSERT INTO STU(ID,NAME) VALUES('56','555555555555');
1 row created.
SQL> commit;
1分钟后在mv site上检查
SQL> select * from stu_mv;
ID         NAME
---------- --------------------
56         555555555555

         六、物化视图与数据迁移

         该方法的实现原理是对于要迁移的表对象,需要有一个主键,用于mv的刷新,对于符合该要求的表,在源表上创建mv日志,再在目标数据库上创建结构一样的表,然后在目标表上采用prebuilt方式创建mv,第一次采用完全刷新,之后采用增量刷新,等真正要切换的时候,只需要刷新完增量的日志,删除mv,保留目标表即可。基本思路的例子:
在源库上创建表和mview log
SQL> create table big_t1 as select * from dba_objects;
Table created.
SQL> select count(1) from big_t1;
  COUNT(1)
----------
     6170
SQL> create materialized view log on big_t1;
Materialized view log created.
在目标数据库上创建与该表一样的表,并在该表上创建prebuilt mv:
SQL> create table big_t1 as select * from big_t1@to_vm9 where 1=2;
Table created.
SQL> select count(1) from big_t1;
  COUNT(1)
----------
      0
SQL> create materialized view big_t1 on prebuilt table refresh fast as select * from big_t1@to_vm9;
Materialized view created.
做完全刷新和增量刷新
SQL> exec dbms_mview.refresh('BIG_T1','Complete');
PL/SQL procedure successfully completed.
SQL> select count(1) from big_t1;
  COUNT(1)
----------
      6170
此时模拟在做完全刷新过程中,源库的表又发生了变化
SQL> insert into big_t1(object_id,owner) values(99991,'test');
1 row created.
SQL> commit;
Commit complete.
再做增量刷新
SQL> select count(1) from big_t1;
  COUNT(1)
----------
      6170
SQL> exec dbms_mview.refresh('BIG_T1');
PL/SQL procedure successfully completed.
SQL> select count(1) from big_t1;
  COUNT(1)
----------
      6171
停机切换,做最后一次刷新,然后删除源库的mview log和目标库的mview
SQL> exec dbms_mview.refresh('BIG_T1');
PL/SQL procedure successfully completed.
SQL> drop materialized view big_t1;
Materialized view dropped.
SQL> select count(1) from big_t1;
  COUNT(1)
----------
      6171
这里删除的mview(big_t1)是prebuilt mv,所以删除该mview,并不删除相应的表。如果删除了mvnew(stu_mv),由于是普通mv,则删除了该mview,就没有对应的表了。
SQL> drop materialized view stu_mv;
Materialized view dropped.
SQL> select * from tab;
TNAME                          TABTYPE  CLUSTERID
------------------------------ ------- ----------
BIG_T1                         TABLE

        

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics