zoukankan      html  css  js  c++  java
  • 物化视图基础概念、mview跨库迁移表

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


    物化视图类型:
    包含聚集的物化视图;只包含连接的物化视图;嵌套物化视图。三种物化视图的快速刷新的限制条件有很大区别,而对于其他方面则区别不大。
     
    创建物化视图时可以指定多种选项,下面对几种主要的选择进行简单说明:
     
    创建方式(Build Methods):
    包括BUILD IMMEDIATE和BUILD DEFERRED两种。BUILD IMMEDIATE是在创建物化视图的时候就生成数据,而BUILD DEFERRED则在创建时不生成数据,以后根据需要在生成数据。默认为BUILD IMMEDIATE。


    查询重写(Query Rewrite):
    包括ENABLE QUERY REWRITE和DISABLE QUERY REWRITE两种。分别指出创建的物化视图是否支持查询重写。查询重写是指当对物化视图的基表进行查询时,Oracle会自动判断能否通过查询物化视图来得到结果,如果可以,则避免了聚集或连接操作,而直接从已经计算好的物化视图中读取数据。默认为DISABLE QUERY REWRITE。
     
    刷新(Refresh):
    指当基表发生了DML操作后,物化视图何时采用哪种方式和基表进行同步。


    刷新的模式有两种:
    ON DEMAND和ON COMMIT。ON DEMAND指物化视图在用户需要的时候进行刷新,可以手工通过DBMS_MVIEW.REFRESH等方法来进行刷新,也可以通过JOB定时进行刷新。 ON COMMIT指出物化视图在对基表的DML操作提交的同时进行刷新。


    刷新的方法有四种:
    FAST、COMPLETE、FORCE和NEVER。FAST刷新采用增量刷新,只刷新自上次刷新以后进行的修改。COMPLETE刷新对整个物化视图进行完全的刷新。如果选择FORCE方式,则Oracle在刷新时会去判断是否可以进行快速刷新,如果可以则采用FAST方式,否则采用COMPLETE的方式。NEVER指物化视图不进行任何刷新。默认值是FORCE ON DEMAND。


    物化视图日志:
    如果需要进行快速刷新,则需要建立物化视图日志。物化视图日志根据不同物化视图的快速刷新的需要,可以建立为ROWID或PRIMARY KEY类型的。还可以选择是否包括SEQUENCE、INCLUDING NEW VALUES以及指定列的列表。物化视图日志表的名称为mlog$_后面跟基表的名称,如果表名的长度超过20位,则只取前20位,当截短后出现名称重复时,oracle会自动在物化视图日志名称后面加上数字作为序号。




    物化视图维护操作:
    1. 创建语句:create materialized view mv_name as select * from table_name    默认情况下,如果没指定刷新方法和刷新模式,则Oracle默认为FORCE和DEMAND。
    2. 创建ON COMMIT物化视图:create materialized view mv_name refresh force on commit as select * from table_name    备注:实际创建过程中,基表需要有主键约束,否则会报错(ORA-12014)
    3.  创建定时刷新的物化视图:create materialized view mv_name refresh force on demand start with sysdate next sysdate+1 (指定物化视图每天刷新一次)
    4.  指定刷新时间(比如每天晚上10:00定时刷新一次):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')
    5. 对于已经创建好的物化视图,可以修改其刷新方式,比如把物化视图mv_name的刷新方式修改为每天晚上10点刷新一次: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')  
    6.  物化视图的删除:drop materialized view mv_name 


    实验操作流程:(同库或者异库迁移同步表)


    流程介绍:该方法的实现原理是对于要迁移的表对象,需要有一个主键,用于mv的刷新,对于符合该要求的表,在源表上创建mv日志,再在目标数据库上创建结构一样的表,然后在目标表上采用prebuilt方式创建mv,第一次采用完全刷新,之后采用增量刷新,等真正要切换的时候,只需要刷新完增量的日志,删除mv,保留目标表即可。


    说明:这里我用同库的两个用户代替异库操作, scott用户代表源库 , andy用户代表目标库。


    1.在源库上创建表和mview log


    SQL> create table andy_01 as select * from dba_objects ;
    Table created.
    SQL> select count(*) from andy_01;


      COUNT(*)
    ----------
        88770
    --为基表建立主键,防止ORA-12014 does not contain a primary key constraint
    SQL> delete from andy_01 where object_id is null;
    SQL> alter table andy_01 add constraint pk_andy_01 primary key(object_id);
    SQL> create materialized view log on andy_01;
    Materialized view log created.
    --源库查询 生成 materialized view log 对象名
    SQL> select object_name from user_objects where object_name like '%MLOG$%';
    OBJECT_NAME
    -----------------------------------------------------------------------------
    I_MLOG$_ANDY_01
    MLOG$_ANDY_01    -> materialized view log 对象名


    2. 授权


    -- 授权目标库用户有查询 源库 materialized view log 的权限
    SQL> grant select on scott.MLOG$_ANDY_01 to andy;
    Grant succeeded.
    SQL> grant select on scott.andy_01 to andy;


    Grant succeeded.


    3.在目标数据库上创建与该表一样的表,并在该表上创建prebuilt mv


    SQL> create table andy_01 as select * from scott.andy_01 where 1=2;       异库加上@dblink_name
    Table created.
    SQL> select count(*) from andy_01;
      COUNT(*)
    ----------
             0
    -- sys用户为目标用户授权
    SQL> GRANT CREATE MATERIALIZED VIEW TO andy;


    Grant succeeded.
    -- 目标库创建 materialized view 
    SQL> create materialized view andy_01 on prebuilt table refresh fast as select * from scott.andy_01;
    Materialized view created.
     
    4.做完全刷新和增量刷新


    SQL> exec dbms_mview.refresh('andy_01','Complete');
    PL/SQL procedure successfully completed.
    SQL>  select count(*) from andy_01;


      COUNT(*)
    ----------
         88765
     
    --此时模拟在做完全刷新过程中,源库的表又发生了变化
    SQL> insert into andy_01(object_id,owner) values(666666,'test');


    1 row created.
    SQL>  commit;


    Commit complete.
    --再做增量刷新
    SQL> select count(*) from andy_01;


      COUNT(*)
    ----------
         88765     
    SQL> exec dbms_mview.refresh('andy_01');
    PL/SQL procedure successfully completed.
     
    SQL> select count(1) from andy_01;


      COUNT(1)
    ----------
         88766


    5.停机切换,做最后一次刷新,然后删除源库的mview log和目标库的mview


    SQL> exec dbms_mview.refresh('andy_01');
    PL/SQL procedure successfully completed.


    6. 迁移完毕,清除 materialized view 与 materialized view log


    -- 清除 目标库 materialized view
    SQL> drop materialized view andy_01;
    Materialized view dropped. 
    SQL> select count(*) from andy_01;
      COUNT(*)
    ----------
         88766
    这里删除的mview(andy_01)是prebuilt mv,所以删除该mview,并不删除相应的表。
    -- 清除源库 materialized view log
    SQL>  drop materialized view log on  ANDY_01;


    Materialized view log dropped.
     
    SQL> select object_name from user_objects where object_name like '%MLOG$%';


    no rows selected

  • 相关阅读:
    原创 记录一次线上Mysql慢查询问题排查过程
    原创 |我是如何解决POI解析Excel出现的OOM问题的?
    FastJson序列化时候出现了$ref?还不赶紧学习下
    fastjson自定义序列化竟然有这么多姿势?
    SpringBoot2.0整合WebSocket,实现后端数据实时推送!
    SpringMVC+Mybatis 如何配置多个数据源并切换?
    异常: java.security.InvalidKeyException: Illegal key size
    一分钟带你了解下MyBatis的动态SQL!
    一分钟带你了解下Spring Security!
    历时七天,史上最强MySQL优化总结,从此优化So Easy!
  • 原文地址:https://www.cnblogs.com/andy6/p/6672827.html
Copyright © 2011-2022 走看看