创建物化视图并定时refresh

来源:互联网 发布:大数据解决方案译见 编辑:程序博客网 时间:2024/06/11 19:18

当我们有报表服务器等系统,为了性能的原因很多时候会使用物化视图,为了保持mview与基表的同步,需要refresh mview.mview的refresh可以分为on commit,on demand,never几种,使用db link的mview不能采用on commit的refresh方式
通常mview根本不需要updateable,所以使用高级复制显然增加了复杂程度,所以就只剩下on demand方式了。需要调用过程dbms_mview.refresh来完成。

我们可以使用某些方式来定时refresh mview.

环境:
orcl01 (主,hostname dg1,用户schema:scott)
orcl02 (mview site,hostname dg2,用户schema:hr)

1.在orcl01上创建materialized view log (fast refresh 需要rowid)
[oracle@dg1 ~]$ sqlplus scott/scott
SQL> create MATERIALIZED VIEW LOG ON emp with rowid;
SQL> create MATERIALIZED VIEW LOG ON dept with rowid;

2.在orcl02上
[oracle@dg2 ~]$ sqlplus / as sysdba
2.1 Hr 用户的权限:
SQL> grant CREATE MATERIALIZED VIEW to hr;
SQL> select * from dba_sys_privs where grantee ='HR' ;

GRANTEE    PRIVILEGE                   ADM
---------- --------------------------- ---
HR         CREATE VIEW                 NO
HR         CREATE MATERIALIZED VIEW    NO
HR         UNLIMITED TABLESPACE        NO
HR         CREATE DATABASE LINK        NO
HR         CREATE SEQUENCE             NO
HR         CREATE SESSION              NO
HR         ALTER SESSION               NO
HR         CREATE SYNONYM              NO

2.2 创建并测试db link (listener,tnsnames.ora已经配置好)
[oracle@dg2 ~]$ sqlplus hr/hr
SQL> create database link priv_link_orcl01_scott connect to scott identified by scott using 'orcl01';
SQL> select count(*) from
emp@priv_link_orcl01_scott;

COUNT(*)
----------
        14

2.3 创建物化视图
SQL> create materialized view testmv_emp_dept
2 refresh fast on demand
3 as
4 select e.rowid "emp_rowid",d.rowid "dept_rowid",e.ename,d.dname,d.loc
5      from emp@priv_link_orcl01_scott e,dept@priv_link_orcl01_scott d
6      where e.deptno = d.deptno;

Materialized view created.

2.4 测试mview
1)在orcl01上:
[oracle@dg1 ~]$ sqlplus scott/scott
SQL> update emp set ename='CLARKCLARK' where ename='CLARK';

1 row updated.

SQL> commit;

Commit complete.

因为materialized view 创建的是on demand的,所以上面的修改并不会自己refresh到Orcl02上,需要执行dbms_mview.refresh:
2)在orcl02上
[oracle@dg2 ~]$ sqlplus hr/hr
SQL> exec DBMS_MVIEW.REFRESH (list=>'TESTMV_EMP_DEPT');

PL/SQL procedure successfully completed.

(默认情况下dbms_mview.refresh的参数purge_option=1,意思是:refresh完成mview log会被purge
这个在orcl01上查询mview log可以看到:
SQL> select * from MLOG$_EMP;
no rows selected)

SQL> select * from testmv_emp_dept;

emp_rowid                        dept_rowid                          ENAME        DNAME             LOC
-----------------------------    -------------------------------- ------------- ------------------   -------------
AAAMgJAAEAAAAAgAAI   AAAMgHAAEAAAAAQAAA KINGKING   ACCOUNTING     NEW YORK
AAAMgJAAEAAAAAgAAN AAAMgHAAEAAAAAQAAA MILLER      ACCOUNTING     NEW YORK
AAAMgJAAEAAAAAgAAD AAAMgHAAEAAAAAQAAB JONES       RESEARCH         DALLAS
AAAMgJAAEAAAAAgAAM AAAMgHAAEAAAAAQAAB FORD        RESEARCH         DALLAS
AAAMgJAAEAAAAAgAAK AAAMgHAAEAAAAAQAAB ADAMS       RESEARCH        DALLAS
AAAMgJAAEAAAAAgAAA AAAMgHAAEAAAAAQAAB SMITH        RESEARCH        DALLAS
AAAMgJAAEAAAAAgAAH AAAMgHAAEAAAAAQAAB SCOTT       RESEARCH        DALLAS
AAAMgJAAEAAAAAgAAC AAAMgHAAEAAAAAQAAC WARD        SALES               CHICAGO
AAAMgJAAEAAAAAgAAJ AAAMgHAAEAAAAAQAAC TURNER     SALES               CHICAGO
AAAMgJAAEAAAAAgAAB AAAMgHAAEAAAAAQAAC ALLEN        SALES               CHICAGO
AAAMgJAAEAAAAAgAAL AAAMgHAAEAAAAAQAAC JAMES        SALES              CHICAGO
AAAMgJAAEAAAAAgAAF AAAMgHAAEAAAAAQAAC BLAKE        SALES              CHICAGO
AAAMgJAAEAAAAAgAAE AAAMgHAAEAAAAAQAAC MARTIN       SALES              CHICAGO
AAAMgJAAEAAAAAgAAG AAAMgHAAEAAAAAQAAA CLARKCLARK   ACCOUNTING     NEW YORK

14 rows selected.
显然orcl01的修改已经refresh到orcl02上的mview.

3.定时refresh
为了定时执行refresh,有几种方式:
1) dbms_job来定时调用exec DBMS_MVIEW.REFRESH (list=>'TESTMV_EMP_DEPT');
2) dbms_refresh来执行
3) unix cron定时执行一个shell 由它来调用sqlplus 执行exec DBMS_MVIEW.REFRESH (list=>'TESTMV_EMP_DEPT');

下面只介绍2. dbms_refresh

dbms_refresh的说明:
DBMS_REFRESH enables you to create groups of materialized views that can be refreshed together
to a transactionally consistent point in time.
优势:分组、事务一致性

创建refresh group
SQL> BEGIN
2     DBMS_REFRESH.MAKE (
3        name => 'hr_refg',
4        list => 'TESTMV_EMP_DEPT',
5        next_date => SYSDATE,
6        interval => 'SYSDATE + 1/288');
7 END;
8 /

PL/SQL procedure successfully completed.

上面的过程会创建refresh group,并且添加定时执行等信息到job中添加的job:
SQL> select job,log_user,to_char(next_date,'DD-MON-YYYY HH24:MI:SS') next_date,
2 interval,what from user_jobs;


JOB LOG_USER   NEXT_DATE            INTERVAL              WHAT
------ ---------- --------------------------       --------------------    ----------------------------------------
       1 HR         02-APR-2008 16:54:15   SYSDATE + 1/288 dbms_refresh.refresh('"HR"."HR_REFG"');

refresh group:
SQL> select rowner,rname,job from user_refresh;

ROWNER                         RNAME                                 JOB
------------------------------ ------------------------------ ----------
HR                             HR_REFG                                 1       

refresh group中的object:
SQL> select owner,name,rname from user_refresh_children;

OWNER     NAME               RNAME
--------- ------------------ ----------
HR        TESTMV_EMP_DEPT    HR_REFG

如果还需要添加其他的物化试图则使用下面的例子:
BEGIN
   DBMS_REFRESH.ADD (
      name => 'hr_refg',
      list => 'hr.employees_mv2';
END;
/