Oracle物化视图的快速刷新机制是通过物化视图日志完成的。Oracle如何通过一个物化视图日志就可以支持多个物化视图的快速刷新呢,本文简单的描述一下刷新的原理。

首先,看一下物化视图的结构:

SQL> create table t (id number, name varchar2(30), num number);

表已创建。

SQL> create materialized view log on t with rowid, sequence (id, name) including new values ;

实体化视图日志已创建。

SQL> desc mlog$_t

名称                                     是否为空? 类型

---------------------------------------- -------- ------------

ID                                                NUMBER

NAME                                              VARCHAR2(30)

M_ROW$$                                           VARCHAR2(255)

SEQUENCE$$                                        NUMBER

SNAPTIME$$                                        DATE

DMLTYPE$$                                         VARCHAR2(1)

OLD_NEW$$                                         VARCHAR2(1)

CHANGE_VECTOR$$                                   RAW(255)

ID和NAME是建立物化视图日志时指定的基表中的列,它们记录每次DML操作对应的ID和NAME的值。

M_ROW$$保存基表的ROWID信息,根据M_ROW$$中的信息可以定位到发生DML操作的记录。

SEQUENCE$$根据DML操作发生的顺序记录序列的编号,当刷新时,根据SEQUENCE$$中的顺序就可以和基表中的执行顺序保持一致。

SNAPTIME$$列记录了刷新操作的时间。

DMLTYPE$$的记录值I、U和D,表示操作是INSERT、UPDATE还是DELETE。

OLD_NEW$$表示物化视图日志中保存的信息是DML操作之前的值(旧值)还是DML操作之后的值(新值)。除了O和N这两种类型外,对于UPDATE操作,还可能表示为U。

CHANGE_VECTOR$$记录DML操作发生在那个或那几个字段上。

有关物化视图日志结构的详细描述,可以参考文档:

物化视图日志结构:http://blog.itpub.net/post/468/20498

根据上面的描述,可以发现,当刷新物化视图时,只需要根据SEQUENCE$$列给出的顺序,通过M_ROW$$定位到基表的记录,如果是UPDATE操作,通过CHANGE_VECTOR$$定位到字段,然后根据基表中的数据重复执行DML操作。

如果物化视图日志只针对一个物化视图,那么刷新过程就是这么简单,还需要做的不过是在刷新之后将物化视图日志清除掉。

但是,Oracle的物化视图日志是可以同时支持多个物化视图的快速刷新的,也就是说,物化视图在刷新时还必须判断哪些物化视图日志记录是当前物化视图刷新需要的,哪些是不需要的。而且,物化视图还必须确定,在刷新物化视图后,物化视图日志中哪些记录是需要清除的,哪些是不需要清除的。

回顾一下物化视图日志的结构,发现只剩下一个SHAPTIME$$列,那么Oracle如何仅通过这一列就完成了对多个物化视图的支持呢?下面建立一个小例子,通过例子来进行说明。

使用上文中建立的表和物化视图日志,下面对这个表建立三个快速刷新的物化视图。

SQL> create materialized view mv_t_id refresh fast as

2  select id, count(*) from t group by id;

实体化视图已创建。

SQL> create materialized view mv_t_name refresh fast as

2  select name, count(*) from t group by name;

实体化视图已创建。

SQL> create materialized view mv_t_id_name refresh fast as

2  select id, name, count(*) from t group by id, name;

实体化视图已创建。

SQL> insert into t values (1, 'a', 2);

已创建 1 行。

SQL> insert into t values (1, 'b', 3);

已创建 1 行。

SQL> insert into t values (2, 'a', 5);

已创建 1 行。

SQL> insert into t values (3, 'b', 7);

已创建 1 行。

SQL> update t set name = 'c' where id = 3;

已更新 1 行。

SQL> delete t where id = 2;

已删除 1 行。

SQL> select id, name, m_row$$, snaptime$$, dmltype$$ from mlog$_t;

ID NAME       M_ROW$$            SNAPTIME$$          D

---------- ---------- ------------------ ------------------- -

1 a          AAACJEAAFAAAAD4AAA 4000-01-01 00:00:00 I

1 b          AAACJEAAFAAAAD4AAB 4000-01-01 00:00:00 I

2 a          AAACJEAAFAAAAD4AAC 4000-01-01 00:00:00 I

3 b          AAACJEAAFAAAAD4AAD 4000-01-01 00:00:00 I

3 b          AAACJEAAFAAAAD4AAD 4000-01-01 00:00:00 U

3 c          AAACJEAAFAAAAD4AAD 4000-01-01 00:00:00 U

2 a          AAACJEAAFAAAAD4AAC 4000-01-01 00:00:00 D

已选择7行。

当发生了DML操作后,物化视图日志中的SNAPTIME$$列保持的值是4000-01-01 00:00:00。这个值表示这条记录还没有被任何物化视图刷新过。第一个刷新这些记录的物化视图会将SNAPTIME$$的值更新为物化视图当前的刷新时间。

SQL> exec dbms_mview.refresh('MV_T_ID')

PL/SQL 过程已成功完成。

SQL> select id, name, m_row$$, snaptime$$, dmltype$$ from mlog$_t;

ID NAME       M_ROW$$            SNAPTIME$$          D

---------- ---------- ------------------ ------------------- -

1 a          AAACJEAAFAAAAD4AAA 2005-03-06 00:56:59 I

1 b          AAACJEAAFAAAAD4AAB 2005-03-06 00:56:59 I

2 a          AAACJEAAFAAAAD4AAC 2005-03-06 00:56:59 I

3 b          AAACJEAAFAAAAD4AAD 2005-03-06 00:56:59 I

3 b          AAACJEAAFAAAAD4AAD 2005-03-06 00:56:59 U

3 c          AAACJEAAFAAAAD4AAD 2005-03-06 00:56:59 U

2 a          AAACJEAAFAAAAD4AAC 2005-03-06 00:56:59 D

已选择7行。

Oracle根据数据字典中的信息可以知道表T上建立了三个物化视图,因此,MV_T_ID刷新完之后,不会删除物化视图记录。

Oracle的数据字典中还保存着每个物化视图上次刷新的时间和当前的刷新状态。

SQL> select name, last_refresh from user_mview_refresh_times;

NAME                           LAST_REFRESH

------------------------------ -------------------

MV_T_ID                        2005-03-06 00:56:59

MV_T_ID_NAME                   2005-03-06 00:46:09

MV_T_NAME                      2005-03-06 00:46:04

SQL> select mview_name, last_refresh_date, staleness from user_mviews;

MVIEW_NAME                     LAST_REFRESH_DATE   STALENESS

------------------------------ ------------------- -------------------

MV_T_ID                        2005-03-06 00:56:59 FRESH

MV_T_ID_NAME                   2005-03-06 00:46:09 NEEDS_COMPILE

MV_T_NAME                      2005-03-06 00:46:04 NEEDS_COMPILE

这些视图中记录了每个物化视图上次执行刷新操作的时间,并且给出每个物化视图中的数据是否是和基表同步的。由于MV_T_ID刚刚进行了刷新,因此状态是FRESH,而另外两个由于在刷新(建立)之后,基表又进行了DML操作,因此状态为NEEDS_COMPILE。如果这时对基表进行DML操作,则MV_T_ID的状态也会变为NEEDS_COMPILE。

SQL> insert into t values (4, 'd', 10);

已创建 1 行。

SQL> commit;

提交完成。

SQL> select id, name, m_row$$, snaptime$$, dmltype$$ from mlog$_t;

ID NAME       M_ROW$$            SNAPTIME$$          D

---------- ---------- ------------------ ------------------- -

1 a          AAACJEAAFAAAAD4AAA 2005-03-06 00:56:59 I

1 b          AAACJEAAFAAAAD4AAB 2005-03-06 00:56:59 I

2 a          AAACJEAAFAAAAD4AAC 2005-03-06 00:56:59 I

3 b          AAACJEAAFAAAAD4AAD 2005-03-06 00:56:59 I

3 b          AAACJEAAFAAAAD4AAD 2005-03-06 00:56:59 U

3 c          AAACJEAAFAAAAD4AAD 2005-03-06 00:56:59 U

2 a          AAACJEAAFAAAAD4AAC 2005-03-06 00:56:59 D

4 d          AAACJEAAFAAAAD4AAE 4000-01-01 00:00:00 I

已选择8行。

SQL> select mview_name, last_refresh_date, staleness from user_mviews;

MVIEW_NAME                     LAST_REFRESH_DATE   STALENESS

------------------------------ ------------------- -------------------

MV_T_ID                        2005-03-06 00:56:59 NEEDS_COMPILE

MV_T_ID_NAME                   2005-03-06 00:46:09 NEEDS_COMPILE

MV_T_NAME                      2005-03-06 00:46:04 NEEDS_COMPILE

下面刷新物化视图MV_T_ID_NAME,刷新操作的判断依据是,只刷新SNAPTIME$$列大于当前物化视图的LAST_REFRESH_DATE的记录,由于物化视图日志中所有记录的SNAPTIME$$的值都比物化视图MV_T_ID_NAME上次刷新的时间点大,因此会刷新所有记录。对于SNAPTIME$$列的值是4000-01-01 00:00:00的记录,物化视图会把SNAPTIME$$列的值更新为当前刷新时间,对于那些已经被更新过的SNAPTIME$$列,则保持原值。

SQL> exec dbms_mview.refresh('MV_T_ID_NAME')

PL/SQL 过程已成功完成。

SQL> select id, name, m_row$$, snaptime$$, dmltype$$ from mlog$_t;

ID NAME       M_ROW$$            SNAPTIME$$          D

---------- ---------- ------------------ ------------------- -

1 a          AAACJEAAFAAAAD4AAA 2005-03-06 00:56:59 I

1 b          AAACJEAAFAAAAD4AAB 2005-03-06 00:56:59 I

2 a          AAACJEAAFAAAAD4AAC 2005-03-06 00:56:59 I

3 b          AAACJEAAFAAAAD4AAD 2005-03-06 00:56:59 I

3 b          AAACJEAAFAAAAD4AAD 2005-03-06 00:56:59 U

3 c          AAACJEAAFAAAAD4AAD 2005-03-06 00:56:59 U

2 a          AAACJEAAFAAAAD4AAC 2005-03-06 00:56:59 D

4 d          AAACJEAAFAAAAD4AAE 2005-03-06 01:18:22 I

已选择8行。

SQL> select mview_name, last_refresh_date, staleness from user_mviews;

MVIEW_NAME                     LAST_REFRESH_DATE   STALENESS

------------------------------ ------------------- -------------------

MV_T_ID                        2005-03-06 00:56:59 NEEDS_COMPILE

MV_T_ID_NAME                   2005-03-06 01:18:22 FRESH

MV_T_NAME                      2005-03-06 00:46:04 NEEDS_COMPILE

如果这时再次刷新物化视图MV_T_ID,则只有ID=4的这条记录的SNAPTIME$$的时间点大于MV_T_ID上次刷新的时间点,因此,只刷新这一条记录,且不会改变SNAPTIME$$的值。

SQL> exec dbms_mview.refresh('MV_T_ID')

PL/SQL 过程已成功完成。

SQL> select id, name, m_row$$, snaptime$$, dmltype$$ from mlog$_t;

ID NAME       M_ROW$$            SNAPTIME$$          D

---------- ---------- ------------------ ------------------- -

1 a          AAACJEAAFAAAAD4AAA 2005-03-06 00:56:59 I

1 b          AAACJEAAFAAAAD4AAB 2005-03-06 00:56:59 I

2 a          AAACJEAAFAAAAD4AAC 2005-03-06 00:56:59 I

3 b          AAACJEAAFAAAAD4AAD 2005-03-06 00:56:59 I

3 b          AAACJEAAFAAAAD4AAD 2005-03-06 00:56:59 U

3 c          AAACJEAAFAAAAD4AAD 2005-03-06 00:56:59 U

2 a          AAACJEAAFAAAAD4AAC 2005-03-06 00:56:59 D

4 d          AAACJEAAFAAAAD4AAE 2005-03-06 01:18:22 I

已选择8行。

SQL> select mview_name, last_refresh_date, staleness from user_mviews;

MVIEW_NAME                     LAST_REFRESH_DATE   STALENESS

------------------------------ ------------------- -------------------

MV_T_ID                        2005-03-06 01:25:30 FRESH

MV_T_ID_NAME                   2005-03-06 01:18:22 FRESH

MV_T_NAME                      2005-03-06 00:46:04 NEEDS_COMPILE

到目前为止,还没有看到过物化视图日志的清除,其实每次进行完刷新,物化视图日志都会试图删除没有用的物化视图日志记录。物化视图日志记录的删除条件是删除那些SNAPTIME$$列小于等于基表所有物化视图的上次刷新时间。在上面的例子中,由于MV_T_NAME一直没有刷新,因此它的LAST_REFRESH_DATE比物化视图日志中所有记录的值都小,因此,一直没有发生物化视图日志记录清除的现象。

SQL> insert into t values (5, 'e', 2);

已创建 1 行。

SQL> commit;

提交完成。

SQL> exec dbms_mview.refresh('MV_T_NAME')

PL/SQL 过程已成功完成。

SQL> select id, name, m_row$$, snaptime$$, dmltype$$ from mlog$_t;

ID NAME       M_ROW$$            SNAPTIME$$          D

---------- ---------- ------------------ ------------------- -

5 e          AAACJEAAFAAAAD4AAF 2005-03-06 01:31:33 I

SQL> select mview_name, last_refresh_date, staleness from user_mviews;

MVIEW_NAME                     LAST_REFRESH_DATE   STALENESS

------------------------------ ------------------- -------------------

MV_T_ID                        2005-03-06 01:25:30 NEEDS_COMPILE

MV_T_ID_NAME                   2005-03-06 01:18:22 NEEDS_COMPILE

MV_T_NAME                      2005-03-06 01:31:33 FRESH

物化视图MV_T_NAME刷新了物化视图中的每条记录,更新了ID=5的记录的SNAPTIME$$时间,并清除了其它所有物化视图日志记录。

最后,简单总结一下:

物化视图在刷新时,会刷新所有SNAPTIME$$大于本物化视图上次刷新时间的记录,并将所有是4000-01-01 00:00:00的记录更新为当前刷新时间。对于其他大于上次刷新时间的记录,只刷新不更改。这样,当刷新执行完以后,数据字典中记录当前物化视图的上次刷新时间为当前时刻,这保证了物化视图日志中目前所有的记录都小于或等于刷新时间。因此,每个物化视图只要刷新大于上次刷新时间的记录,且保证每次刷新后,所有记录的时间都小于等于上次刷新时间,那么无论有多少个物化视图,就可以互不影响的使用同一个物化视图日志进行快速刷新了。当物化视图刷新完之后,会清除那些SNAPTIME$$列小于所有物化视图的上次刷新时间的记录,而这些记录已经被所有的物化视图都刷新过了,保存在物化视图日志中已经没有意义了。

出自:http://blog.itpub.net/post/468/20584

oracle视图查询机制,物化视图及日志内部机制的一点研究相关推荐

  1. Oracle 如何根据物化视图日志快速刷新物化视图 (不积跬步,无以至千里)

    Oracle物化视图的快速刷新机制是通过物化视图日志完成的.Oracle如何通过一个物化视图日志就可以支持多个物化视图的快速刷新呢,本文简单的描述一下刷新的原理. 首先,看一下物化视图的结构: SQL ...

  2. oracle雾化试图_Oracle 物化视图 说明

    一.    物化视图概述 Oracle的物化视图是包括一个查询结果的数据库对像,它是远程数据的的本地副本,或者用来生成基于数据表求和的汇总表.物化视图存储基于远程表的数据,也可以称为快照. 物化视图可 ...

  3. oracle雾化试图_Oracle物化视图语法

    物化视图概述: Oracle的物化视图提供了强大的功能,可以用在不同的环境中.在不同的环境中,物化视图的作用也不相同.数据仓库中的物化视图主要用于预先计算并保存表连接或聚集等耗时较多的操作的结果,这样 ...

  4. 创建数据库_详解Oracle数据库物化视图及创建物化视图索引

    概述 物化视图是一种特殊的物理表,"物化"(Materialized)视图是相对普通视图而言的.普通视图是虚拟表,应用的局限性大,任何对视图的查询,Oracle都实际上转换为视图S ...

  5. oracle雾化试图_ORACLE物化视图具体解释

    一.物化的一般使用方法物化视图是一种特殊的物理表,"物化"(Materialized)视图是相对普通视图而言的.普通视图是虚拟表,应用的局限性大,不论什么对视图的查询,oracle ...

  6. SQL Server索引视图以(物化视图)及索引视图与查询重写

    SQL Server索引视图以(物化视图)及索引视图与查询重写 本文出处:http://www.cnblogs.com/wy123/p/6041122.html 经常听Oracle的同学说起来物化视图 ...

  7. oracle 物化视图没效果,物化视图失效的几种情况及测试

    说明:物化视图(Materialized Views)是查询的结果集,所有原表和视图的变更都将导致物化视图的失效,最近就发现了一个物化视图经常失效的问题,以下是整理的文档. 一.物化视图状态查询:OR ...

  8. 傅老师课堂:Oracle高级应用之物化视图(materialized view)

    原文地址:http://hi.baidu.com/gukeming888/blog/item/2682f69481c8237154fb9662.html 物化视图 (Materialized View ...

  9. mysql 物化视图 更新_物化视图的快速刷新测试与物化视图日志

    前言:一般在创建物化视图的时候,在数据量不大的时候,刷新的方式都是采用完全刷新的.随着系统的使用一些物化视图的源表的数据量在不断的增长,原本采用完全方式几秒就能刷新完成的物化视图,现在需要等待很久的时 ...

最新文章

  1. 总监调岗至前台,企业被判赔偿26万,法院:“侮辱性调岗”违法!
  2. 学习python时报SyntaxError: Non-ASCII character '\xe5' in file解决方法
  3. 将资源文件中的数据写回磁盘
  4. PE经典DIY案例1:全解开方案让量产PE也能
  5. cd : cannot create temp file for here-document: No space left on device
  6. win7安装python开发环境,运行python
  7. 最流行的 .NET 开源项目合集
  8. HTML期末作业-宠物网
  9. jquery梳理之常用选择器
  10. HTML的iframe标签的滚动条
  11. Power Platform 零基础 Power Apps canvas+Power Automate 画布应用基础搭建应用流程
  12. run()方法和start()方法的区别
  13. 百度云语音合成 Python SDK
  14. ftpserver配置
  15. scanf函数的返回值以及在while循环中的应用
  16. stm32f103电子钟心得体会_STM32时钟小结
  17. splash占用内存越来越大的问题
  18. AnLink打通电脑与手机操作和数据互通的专用工具
  19. LeetCode——面试题 16.19. 水域大小
  20. 开展新闻公关推广必须掌握的5个要点

热门文章

  1. 开环直流电机的机械特性_无刷直流电动机的开环调速机械特性研究
  2. 内存分配器ptmalloc,jemalloc,tcmalloc调研与对比
  3. Python库:内存监控模块memory_profiler(待完善)
  4. css高度自适应以及高度塌陷总结
  5. android远程调用github仓库的aar文件
  6. 排列和组合、以及数列(五)
  7. Android2D绘图二
  8. mybatis 原理_Mybatis大揭秘:plugin插件设计原理
  9. java编程算法出现在窗口_Java实现轨迹压缩算法开放窗口代码编程实例分享
  10. hadoop tyarn冲突_Doris与Hadoop yarn混合部署遇到的坑