oracle 物化视图 -循序渐进MView(三) 基于ROWID的MView
来源:互联网 发布:网络社交平台有哪些 编辑:程序博客网 时间:2024/06/04 08:11
- http://www.dbabeta.com/2009/mview_step_by_step_03.html
- 前言
- 基于ROWID的MView
- 基于ROWID MView的创建
- 基于ROWID MView的快速刷新
- 基于ROWID MView的MView Log结构
- 怎么把基于ROWID的MView转换成基于PK的MView
- 转换基于ROWID的MView到基于PK(全刷型)
- 转换基于ROWID的MView到基于PK(非全刷型)
- 参考资料
前言
前面我们已经说了MView的一些基本知识,我们举得例子都是基于PK的MView,Oracle还支持其他方式的MView,基于ROWID的MView就是其中的一种。在这一部分将讨论如何建立基于ROWID的MView,同时分析下MView Log的结构。
基于ROWID的MView
基于ROWID MView的创建
还是先用一个例子开始:
USER@orcl> create table T4 (a int, b varchar(40));
Table created.
-- 建立一个MView,这是Oracle报错了
USER@orcl> create materialized view mvt4 as select * from t4;
create materialized view mvt4 as select * from t4
*
ERROR at line 1:
ORA-12014: table 'T4' does not contain a primary key constraint
默认情况下Oracle是按照基于PK的方式来建立MView的,上面我们建立的测试表是没有PK的,这样Oracle就开始报错了,解决的方法也很简单:在建立MView的时候指定REFRESH WITH ROWID参数,如下
Materialized view created.
接下来我们往里面增加些数据并测试下:
USER@orcl> insert into t4 select rownum, object_name fromall_objects;
11501 rows created.
USER@orcl> commit;
Commit complete.
-- 做一次刷新,OK是没有问题的
USER@orcl> exec dbms_mview.refresh('mvt4', 'c');
PL/SQL procedure successfully completed.
基于ROWID MView的快速刷新
为了保证可以快速刷新,我们还需要给表TT建立MView Log,同样建立MView Log的时候我们一样是要制定WITH ROWID参数的。
Materialized view log created.
现在做一下快速刷新的测试
4 rows updated.
快速刷新没有问题
PL/SQL procedure successfully completed.
基于ROWID MView的MView Log结构
我们先看一下表T4的MView Log的结构
Name Null? Type
---------------- -------- --------------
M_ROW$$ VARCHAR2(255)
SNAPTIME$$ DATE
DMLTYPE$$ VARCHAR2(1)
OLD_NEW$$ VARCHAR2(1)
CHANGE_VECTOR$$ RAW(255)
从结构中可以看出除了 M_ROW$$列之外其他的和基于PK的MView都是一样的,在这里的M_ROW$$保存的基表里面被操作行的ROWID,作用和PK是一样的,在刷新MView的时候用来定位基表以及MView表中的数据列。因为M_ROW$$记录的是基表的行的ROWID,那在MView表中对应行的ROWID肯定是和基表的不一样的,这点和PK是不一样的,PK在那儿都是一样的,为了使MView在刷新是利用MView Log中的M_ROW$$能找到MView表中的对应行,Oracle在MView表中加入了一个隐藏列,这个列从DBA_TAB_COLUMNS里面是看不到的,要从SYS.COL$里面才能看到,下面我们把这个列查出来看看
USER@orcl> SELECT COLUMN_NAME FROM DBA_TAB_COLUMNS WHERETABLE_NAME='MVT4';
COLUMN_NAME
------------------------------
A
B
-- 从SYS.COL$里面就能看到我们的隐藏列M_ROW$$了
USER@orcl> SELECT NAME FROM SYS.COL$ WHERE OBJ# IN (SELECT OBJECT_ID FROM DBA_OBJECTS WHERE OBJECT_NAME = 'MVT4');
NAME
--------------------
A
B
M_ROW$$
下面来验证一下这个隐藏列中的数据,先修改下表T4的数据
4 rows updated.
接下来我们对比下表T4中被修改的数据的ROWID,MView Log MLOG$_T4中的M_ROW$$列以及MView MVT4中的M_ROW$$数据
ROWID A B
------------------ ---------- ----------------------------------------
AAAIQlAAIAAAgVMAAA 371 I_SUMAGG$_1
AAAIQlAAIAAAgVMAAB 372 SUMJOIN$
AAAIQlAAIAAAgVMAAC 373 I_SUMJOIN$_1
AAAIQlAAIAAAgVMAAD 374 SUMDEP$
USER@orcl> select * from mlog$_t4;
M_ROW$$ SNAPTIME$$ D O CHANGE_VEC
------------------------------ ------------------- - - ----------
AAAIQlAAIAAAgVMAAA 4000-01-01 00:00:00 U U 04
AAAIQlAAIAAAgVMAAB 4000-01-01 00:00:00 U U 04
AAAIQlAAIAAAgVMAAC 4000-01-01 00:00:00 U U 04
AAAIQlAAIAAAgVMAAD 4000-01-01 00:00:00 U U 04
USER@orcl> select M_ROW$$, rowid, a, b from mvt4 where M_ROW$$ IN(SELECT M_ROW$$ FROM mlog$_t4);
M_ROW$$ ROWID A B
------------------------------ ------------------ ---------- ----------------------------------------
AAAIQlAAIAAAgVMAAA AAAIQgAAIAAAgUgACX 371I_SUMAGG$_1
AAAIQlAAIAAAgVMAAB AAAIQgAAIAAAgUgACY 372SUMJOIN$
AAAIQlAAIAAAgVMAAC AAAIQgAAIAAAgUgACZ 373I_SUMJOIN$_1
AAAIQlAAIAAAgVMAAD AAAIQgAAIAAAgUgACa 374 SUMDEP$
通过实验可以看出来MVT4中的隐藏列M_ROW$$起的作用和PK是一样的。同时为了保证刷新速度,Oracle还在这一列上面建立了一个索引,索引的命名方式为I_SNAP$_mview_name,这个我们可以从DBA_INDEXES和DBA_IND_COLUMNS里面查到:
STATUS,GENERATED FROM DBA_INDEXES WHERE TABLE_NAME='MVT4';
INDEX_NAME INDEX_TYPE TABLE_NAME UNIQUENES STATUS G
------------- ----------- ----------- --------- -------- -
I_SNAP$_MVT4 NORMAL MVT4 UNIQUE VALID N
USER@orcl> SELECT INDEX_NAME,TABLE_NAME,COLUMN_NAME FROMDBA_IND_COLUMNS WHERE INDEX_NAME='I_SNAP$_MVT4';
INDEX_NAME TABLE_NAME COLUMN_NAME
------------- ----------- -----------
I_SNAP$_MVT4 MVT4 M_ROW$$
由于MView Log使用的是ROWID来进行操作,因此当基表的ROWID被改变以后将会导致MView无法快速刷新,发生这种情况只有做全刷了。
Table altered.
USER@orcl> exec dbms_mview.refresh('mvt4','f');
BEGIN dbms_mview.refresh('mvt4','f'); END;
*
ERROR at line 1:
ORA-12034: materialized view log on "USER"."T4" younger than lastrefresh
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2255
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2461
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2430
ORA-06512: at line 1
USER@orcl> exec dbms_mview.refresh('mvt4','c');
PL/SQL procedure successfully completed.
怎么把基于ROWID的MView转换成基于PK的MView
有时候我们会要求将基于ROWID的MView转换成基于PK的MView,为了达到这个目的有两种方法,第一种方法删除MView Log然后在修改MView属性之后重建MView Log,这种方法要求对MView进行全部刷新;另外一种方法是通过修改MView Log来进行,这种方法可以做到不全刷MView,不过只能在8i以后的版本执行,当然这在现在不是个问题。
转换基于ROWID的MView到基于PK(全刷型)
这里我们先将现有的MView Log删除,然后在对MView做全刷。
首先在将基表上的MView Log删除,然后在使用WITH PRIMARY KEY重新建立MView Log
Table altered.
USER@orcl> drop materialized view log on t4;
Materialized view log dropped.
USER@orcl> create materialized view log on t4 with primary key;
Materialized view log created.
然后修改我们的MView,完了之后做一次全刷
Materialized view altered.
USER@orcl> exec dbms_mview.refresh('mvt4','c');
PL/SQL procedure successfully completed.
现在我们的转换工作已经完成,以后就可以对MView进行快速刷新了
转换基于ROWID的MView到基于PK(非全刷型)
做这种方式的刷新需要保证我们的基表和MView都跑在8i或者以后的版本上。
首先我们修改我们的MView Log,增加Primary Key进去。
Materialized view log altered.
接下来我们对基表的所有的MView都做一次快速刷新。
注意:这个步骤是非常必要的,目的是确保在修改完MView Log之后我们的MView快速刷新能正常工作,否则的话将会出现ORA-12034错误并要求你做全刷,这样就全功尽弃了。
PL/SQL procedure successfully completed.
然后我们再去修改MView,完了之后可以做快速刷新了
Materialized view altered.
USER@orcl> exec dbms_mview.refresh('mvt4','f');
PL/SQL procedure successfully completed.
这种方法还有一个遗留问题就是虽然我们现在不需要ROWID来进行刷新了,但是MView Log还是照样会把ROWID记录在里面的,这个会使MView比通常要大些。
- oracle 物化视图 -循序渐进MView(三) 基于ROWID的MView
- oracle 物化视图 -循序渐进MView(三) 基于ROWID的MView
- 循序渐进MView(三) 基于ROWID的MView
- ORACLE物化视图 - 循序渐进MView(一) 什么是MView
- ORACLE物化视图- 循序渐进MView(六) MView管理
- ORACLE物化视图--循序渐进MView(二) MView Log的结构与快速刷新
- ORACLE物化视图 -循序渐进MView(四) MView创建语法参考
- ORACLE物化视图-循序渐进MView(五) 利用刷新组控制MView刷新
- Oracle的实体化视图(MVIEW)的深入研究之三
- Oracle的实体化视图(MVIEW)的深入研究之三
- Oracle的实体化视图(MVIEW)的深入研究之一
- Oracle的实体化视图(MVIEW)的深入研究之二
- Oracle的实体化视图(MVIEW)的深入研究之四
- Oracle的实体化视图(MVIEW)的深入研究之四
- Oracle的实体化视图(MVIEW)的深入研究之二
- Oracle的实体化视图(MVIEW)的深入研究之一
- 物化视图基础概念、mview跨库迁移表
- oracle字符集引发mview的血案
- python hex string 转成 bytes
- Java基础之面向对象(抽象类、接口、内部类)
- Android 属性系统(SystemProperties)
- MATLAB常用日期和时间函数
- java写的Socket客户端和服务端通信,经验证可以执行的代码,并添加了很多注释
- oracle 物化视图 -循序渐进MView(三) 基于ROWID的MView
- 设计模式C++描述__职责链(Chain of Responsibility)模式
- CSDN积分
- linux socket通信编程之c语言(客户端和服务器程序)
- Android的日志信息介绍
- unity3d开发的android应用中加入AD系统的具体步骤
- 启动resin多个实例
- 进程与线程的一个简单解释
- fzu_1894 志願者選拔( 單調隊列 )