yangtingkun
===========================================================
物化视图的快速刷新(一)
===========================================================

物化视图有三种刷新方式:COMPLETEFASTFORCE

完全刷新(COMPLETE)会删除表中所有的记录(如果是单表刷新,可能会采用TRUNCATE的方式),然后根据物化视图中查询语句的定义重新生成物化视图。快速刷新(FAST)采用增量刷新的机制,只将自上次刷新以后对基表进行的所有操作刷新到物化视图中去。采用FORCE方式,Oracle会自动判断是否满足快速刷新的条件,如果满足则进行快速刷新,否则进行完全刷新。

显然快速刷新是物化视图刷新方式的首选。但是,不是所有的物化视图都可以进行快速刷新,只有满足某些条件的物化视图才具有快速刷新的能力。

根据查询的不同,快速刷新的限制条件也不相同,下面总结一下不同类型的物化视图对快速刷新的限制条件。

可以参考:

物化视图的快速刷新(二):http://yangtingkun.itpub.net/post/468/16456

物化视图的快速刷新(三):http://yangtingkun.itpub.net/post/468/16496


所有类型的快速刷新物化视图都必须满足的条件:

1.物化视图不能包含对不重复表达式的引用,如SYSDATE和ROWNUM;

2.物化视图不能包含对LONG和LONG RAW数据类型的引用。

只包含连接的物化视图:

1.必须满足所有快速刷新物化视图都满足的条件;

2.不能包括GROUP BY语句或聚集操作;

3.如果在WHERE语句中包含外连接,那么唯一约束必须存在于连接中内表的连接列上;

4.如果不包含外连接,那么WHERE语句没有限制,如果包含外连接,那么WHERE语句中只能使用AND连接,并且只能使用“=”操作。

5.FROM语句列表中所有表的ROWID必须出现在SELECT语句的列表中。

6.FROM语句列表中的所有表必须建立基于ROWID类型的物化视图日志。

下面,我们看一个满足快速刷新条件的例子,然后依次违反上述6个条件,分别测试,查看会出现什么错误。

首先,创建测试环境:

SQL> create table dim_a (id number primary key, name varchar2(30));

表已创建。

SQL> create table dim_b (id number primary key, name varchar2(30));

表已创建。

SQL> create table fact (id number, aid number, bid number, num number);

表已创建。

SQL> alter table fact add constraint fk_fact_aid foreign key (aid) references dim_a(id);

表已更改。

SQL> alter table fact add constraint fk_fact_bid foreign key (bid) references dim_b(id);

表已更改。

SQL> insert into dim_a select rownum, 'a'||rownum from user_objects;

已创建74行。

SQL> insert into dim_b select rownum, 'b'||rownum from user_objects;

已创建74行。

SQL> insert into fact select rownum, mod(rownum, 6) + 1, mod(rownum, 5 ) + 1, rownum *2
2 from user_objects;

已创建74行。

SQL> commit;

提交完成。

接下来建立一个可以成功快速刷新的例子,这个物化视图只包含连接:

SQL> create materialized view log on dim_a with rowid;

实体化视图日志已创建。

SQL> create materialized view log on dim_b with rowid;

实体化视图日志已创建。

SQL> create materialized view log on fact with rowid;

实体化视图日志已创建。

SQL> create materialized view mv_fact refresh fast on commit as
2 select f.rowid f_rowid, a.rowid a_rowid, b.rowid b_rowid, f.id,
3 a.name a_name, b.name b_name, num
4 from fact f, dim_a a, dim_b b
5 where f.aid = a.id
6 and f.bid = b.id;

实体化视图已创建。

下面我们依次违反上面的6个条件,观察错误信息。

1.包含SYSDATE/ROWNUM或RAW/LONG RAW数据类型。

SQL> create materialized view mv_fact_err refresh fast on commit as
2 select f.rowid f_rowid, a.rowid a_rowid, b.rowid b_rowid, f.id,
3 a.name a_name, b.name b_name, num, sysdate time
4 from fact f, dim_a a, dim_b b
5 where f.aid = a.id
6 and f.bid = b.id;
from fact f, dim_a a, dim_b b
*
ERROR 位于第 4 行:
ORA-12054: 无法为实体化视图设置 ON COMMIT 刷新属性

错误提示是不能设置ON COMMIT属性,去掉ON COMMIT语句再次尝试:

SQL> create materialized view mv_fact_err refresh fast as
2 select f.rowid f_rowid, a.rowid a_rowid, b.rowid b_rowid, f.id,
3 a.name a_name, b.name b_name, num, sysdate time
4 from fact f, dim_a a, dim_b b
5 where f.aid = a.id
6 and f.bid = b.id;
from fact f, dim_a a, dim_b b
*
ERROR 位于第 4 行:
ORA-12015: 不能从复杂查询中创建一个可快速刷新的实体化视图

根据预期一样,建立快速刷新的物化视图报错,不过提示信息不明确,很难定位具体问题。使用ROWNUM后报错的提示信息和使用SYSDATE的一样。

可以通过DBMS_MVIEW包的EXPLAIN_MVIEW过程来得到更加详细的错误信息。有关这个包的具体使用方法可以参考:http://blog.itpub.net/post/468/13318

SQL> begin
2 dbms_mview.explain_mview('select f.rowid f_rowid, a.rowid a_rowid, b.rowid b_rowid, f.id,
3 a.name a_name, b.name b_name, num, rownum row_id
4 from fact f, dim_a a, dim_b b
5 where f.aid = a.id
6 and f.bid = b.id');
7 end;
8 /

PL/SQL 过程已成功完成。

SQL> select msgtxt from mv_capabilities_table where capability_name = 'REFRESH_FAST_AFTER_INSERT';

MSGTXT
---------------------------------------
在实体化视图中引用了 ROWNUM

使用这种方法就可以得到更加准确的错误信息了。

测试另外一个约束之前要说明一下,Oracle文档上给出的约束条件是不能包括RAW和LONG RAW类型,根据我的测试结果,估计是文档出现了错误,这里应该是LONG和LONG RAW类型。

SQL> alter table dim_a add (col_raw raw(10) default '1');

表已更改。

SQL> create materialized view mv_fact_err refresh fast on commit as
2 select f.rowid f_rowid, a.rowid a_rowid, b.rowid b_rowid, f.id,
3 a.name a_name, b.name b_name, num, a.col_raw
4 from fact f, dim_a a, dim_b b
5 where f.aid = a.id
6 and f.bid = b.id;

实体化视图已创建。
SQL> update dim_a set col_raw = '2';

已更新74行。

SQL> commit;

提交完成。

SQL> select distinct col_raw from mv_fact_err;

COL_RAW
--------------------
02
SQL> drop materialized view mv_fact_err;

实体化视图已删除。

SQL> alter table dim_a drop (col_raw);

表已更改。

SQL> alter table dim_a add (col_long long default '1');

表已更改。

SQL> create materialized view mv_fact_err refresh fast on commit as
2 select f.rowid f_rowid, a.rowid a_rowid, b.rowid b_rowid, f.id,
3 a.name a_name, b.name b_name, num, a.col_long
4 from fact f, dim_a a, dim_b b
5 where f.aid = a.id
6 and f.bid = b.id;
from fact f, dim_a a, dim_b b
*
ERROR 位于第 4 行:
ORA-00997: 非法使用 LONG 数据类型


SQL> alter table dim_a drop (col_long);

表已更改。

2.不能包括GROUP BY语句或聚集操作

SQL> create materialized view mv_fact_err refresh fast on commit as
2 select f.rowid f_rowid, a.rowid a_rowid, b.rowid b_rowid, f.id,
3 a.name a_name, b.name b_name, count(num) count_num
4 from fact f, dim_a a, dim_b b
5 where f.aid = a.id
6 and f.bid = b.id
7 group by f.rowid, a.rowid, b.rowid, f.id, a.name, b.name;
from fact f, dim_a a, dim_b b
*
ERROR 位于第 4 行:
ORA-32401: "YANGTK"."DIM_B" 上的实体化视图日志没有新值

不管是否存在连接,只要包括聚集操作,就要满足聚集物化视图快速刷新的条件。这个错误提示正是聚集物化视图快速刷新需要满足的条件之一。

3.如果在WHERE语句中包含外连接,那么唯一约束必须存在于连接中内表的连接列上:

SQL> drop materialized view mv_fact;

实体化视图已删除。

SQL> create materialized view mv_fact refresh fast on commit as
2 select f.rowid f_rowid, a.rowid a_rowid, b.rowid b_rowid, f.id,
3 a.name a_name, b.name b_name, num
4 from fact f, dim_a a, dim_b b
5 where f.aid = a.id(+)
6 and f.bid = b.id;

实体化视图已创建。

SQL> drop materialized view mv_fact;

实体化视图已删除。

SQL> alter table fact drop constraint fk_fact_aid;

表已更改。

SQL> alter table dim_a drop primary key;

表已更改。

SQL> create materialized view mv_fact refresh fast on commit as
2 select f.rowid f_rowid, a.rowid a_rowid, b.rowid b_rowid, f.id,
3 a.name a_name, b.name b_name, num
4 from fact f, dim_a a, dim_b b
5 where f.aid = a.id(+)
6 and f.bid = b.id;
from fact f, dim_a a, dim_b b
*
ERROR 位于第 4 行:
ORA-12052: 无法快速刷新实体化视图 YANGTK.MV_FACT

这个错误提示不是很明确,但是Oracle错误消息文档上对这个错误产生的原因已经分析的很清楚了。

ORA-12052 cannot fast refresh materialized view string.string

Cause: Either ROWIDs of certain tables were missing in the definition or the inner table of an outer join did not have UNIQUE constraints on join columns.

Action: Specify the FORCE or COMPLETE option. If this error occurred during creation, the materialized view definition may have been changed. Refer to the documentation on materialized views.

SQL> delete mv_capabilities_table;

已删除13行。

SQL> begin
2 dbms_mview.explain_mview('select f.rowid f_rowid, a.rowid a_rowid, b.rowid b_rowid, f.id,
3 a.name a_name, b.name b_name, num
4 from fact f, dim_a a, dim_b b
5 where f.aid = a.id(+)
6 and f.bid = b.id');
7 end;
8 /

PL/SQL 过程已成功完成。

SQL> select msgtxt from mv_capabilities_table where capability_name = 'REFRESH_FAST_AFTER_INSERT';

MSGTXT
----------------------------------------------------------
在内部表的联接列上没有唯一性约束条件

SQL> alter table dim_a add primary key (id);

表已更改。

SQL> alter table fact add constraint fk_fact_aid foreign key (aid) references dim_a(id);

表已更改。

4.如果不包含外连接,那么WHERE语句没有限制,如果包含外连接,那么WHERE语句中只能使用AND连接,并且只能使用“=”操作:

SQL> create materialized view mv_fact refresh fast on commit as
2 select f.rowid f_rowid, a.rowid a_rowid, b.rowid b_rowid, f.id,
3 a.name a_name, b.name b_name, num
4 from fact f, dim_a a, dim_b b
5 where f.aid = a.id
6 or f.bid = b.id;

实体化视图已创建。

SQL> create materialized view mv_fact_err refresh fast on commit as
2 select f.rowid f_rowid, a.rowid a_rowid, b.rowid b_rowid, f.id,
3 a.name a_name, b.name b_name, num
4 from fact f, dim_a a, dim_b b
5 where f.aid = a.id(+)
6 or f.bid = b.id;
where f.aid = a.id(+)
*
ERROR 位于第 5 行:
ORA-01719: OR 或 IN 操作数中不允许外部连接运算符 (+)

这个错误提示是十分明显的,不过下面的又只能通过EXPLAIN_MVIEW过程来定位错误原因。

SQL> create materialized view mv_fact_err refresh fast on commit as
2 select f.rowid f_rowid, a.rowid a_rowid, b.rowid b_rowid, f.id,
3 a.name a_name, b.name b_name, num
4 from fact f, dim_a a, dim_b b
5 where f.aid = a.id(+)
6 and f.bid != b.id;
from fact f, dim_a a, dim_b b
*
ERROR 位于第 4 行:
ORA-12054: 无法为实体化视图设置 ON COMMIT 刷新属性


SQL> create materialized view mv_fact_err refresh fast as
2 select f.rowid f_rowid, a.rowid a_rowid, b.rowid b_rowid, f.id,
3 a.name a_name, b.name b_name, num
4 from fact f, dim_a a, dim_b b
5 where f.aid = a.id(+)
6 and f.bid != b.id;
from fact f, dim_a a, dim_b b
*
ERROR 位于第 4 行:
ORA-12015: 不能从复杂查询中创建一个可快速刷新的实体化视图


SQL> delete mv_capabilities_table;

已删除15行。

SQL> begin
2 dbms_mview.explain_mview('select f.rowid f_rowid, a.rowid a_rowid, b.rowid b_rowid, f.id,
3 a.name a_name, b.name b_name, num
4 from fact f, dim_a a, dim_b b
5 where f.aid = a.id(+)
6 and f.bid != b.id');
7 end;
8 /

PL/SQL 过程已成功完成。

SQL> select msgtxt from mv_capabilities_table where capability_name = 'REFRESH_FAST_AFTER_INSERT';

MSGTXT
------------------------------------------------------------
使用了除等号 (=) 外的运算符联接谓词
实体化视图中的外部联接
在实体化视图中存在一个或多个联接

5.FROM语句列表中所有表的ROWID必须出现在SELECT语句的列表中:

SQL> create materialized view mv_fact_err refresh fast on commit as
2 select f.rowid f_rowid, a.rowid a_rowid, f.id,
3 a.name a_name, b.name b_name, num
4 from fact f, dim_a a, dim_b b
5 where f.aid = a.id
6 or f.bid = b.id;
from fact f, dim_a a, dim_b b
*
ERROR 位于第 4 行:
ORA-12052: 无法快速刷新实体化视图 YANGTK.MV_FACT_ERR

这个错误的信息在上面已经列出了,错误原因说明比较明确。

SQL> delete mv_capabilities_table;

已删除17行。

SQL> begin
2 dbms_mview.explain_mview('select f.rowid f_rowid, a.rowid a_rowid, f.id,
3 a.name a_name, b.name b_name, num
4 from fact f, dim_a a, dim_b b
5 where f.aid = a.id
6 or f.bid = b.id');
7 end;
8 /

PL/SQL 过程已成功完成。

SQL> select msgtxt from mv_capabilities_table where capability_name = 'REFRESH_FAST_AFTER_INSERT';

MSGTXT
---------------------------------------------------
SELECT 列表没有所有从表的 rowid

6.FROM语句列表中的所有表必须建立基于ROWID类型的物化视图日志。

SQL> drop materialized view log on dim_a;

实体化视图日志已删除。

SQL> drop materialized view mv_fact;

实体化视图已删除。

SQL> create materialized view mv_fact refresh fast on commit as
2 select f.rowid f_rowid, a.rowid a_rowid, b.rowid b_rowid, f.id,
3 a.name a_name, b.name b_name, num
4 from fact f, dim_a a, dim_b b
5 where f.aid = a.id
6 and f.bid = b.id;
from fact f, dim_a a, dim_b b
*
ERROR 位于第 4 行:
ORA-23413: 表 "YANGTK"."DIM_A" 不带实体化视图日志

这个错误说明十分明确,可以直接定位错误原因。

yangtingkun 发表于:2005.01.16 23:55 ::分类: ( ORACLE ) ::阅读:(29244次) :: 评论 (23)
[回复]

呵呵,这个不算深入,不过是把所有的错误重新了一遍而已。smile

yangtingkun 评论于: 2005.03.31 18:40
[回复]

刷新视图,应该还有基于 on demand 形式的啊。

drew 评论于: 2005.12.13 09:53
[回复]

物化视图的种类很多,根据不同的着重点可以有不同的分类
按刷新方式分:FAST/COMPLETE/FORCE

按刷新时间的不同:ON DEMAND/ON COMMIT

按是否可更新:UPDATABLE/READ ONLY

按是否支持查询重写:ENABLE QUERY REWRITE/DISABLE QUERY REWRITE

……

yangtingkun 评论于: 2005.12.13 10:43
re: 物化视图的快速刷新(一) [回复]

请教:我进行了如下操作,报12054错,请问是什么原因呢?谢谢!
在A用户下执行:
create materialized view log on A.rs
Grant create materialized view to B
Grant select on a.rs to B
Grant select on MLOG$_rs to B
Grant on commit refresh on a.rs to B
Grant query rewrite on a.rs to B

在B用户下,执行:
Create materialized view rs_mv
Tablespace test
Build immediate
Refresh fast on commit
Enable query rewrite
As
Select
a1, to_number(a2) ,(a3*100000000+a4*1000000+a5*10000+a5),
a6,
FROM Rs@link_test
Where a6>1000

其中link_test 事先建好了

错误信息:
ERROR at line 19:
ORA-12054: cannot set the ON COMMIT refresh attribute for the materialized view

小山 评论于: 2006.12.25 17:36
re: 物化视图的快速刷新(一) [回复]

设置REFRESH ON COMMIT的物化视图不能访问远端对象

yangtingkun 评论于: 2006.12.25 18:32
re: 物化视图的快速刷新(一) [回复]

再请教:设置REFRESH ON COMMIT的物化视图不能访问远端对象,那么oracle的远程复制是否就无法实现实时刷新了?

小山 评论于: 2006.12.26 11:49
re: 物化视图的快速刷新(一) [回复]

是的

yangtingkun 评论于: 2006.12.26 17:41
re: 物化视图的快速刷新(一) [回复]

谢谢smile

小山 评论于: 2006.12.27 00:54
re: 物化视图的快速刷新(一) [回复]

物化视图中可以嵌套聚集函数吗?如:nvl(sum(a),0)或者是decode(,,decode(,,))

lisongyang 评论于: 2007.08.22 15:33
re: 物化视图的快速刷新(一) [回复]

这样将无法快速刷新

yangtingkun 评论于: 2007.08.27 09:56
re: 物化视图的快速刷新(一) [回复]

请教:
1、现有三张表,来自三个不同的远程数据库,要求在这三张表基础上,本地创建快速刷新物化视图.并能实现数据的刷新(只需按月就刷新就行).
是不是如楼上小山所述的那种方法啊?
2、物化视图复制站点,主站点这些是什么意思,我需要用到这些吗?

lisongyang 评论于: 2007.09.03 15:36
re: 物化视图的快速刷新(一) [回复]

如果你在本地数据库不进行修改是不需要建立物化视图复制机制的。

直接建立一个物化视图就可以了。
至于你的物化视图能否快速刷新,取决于你的物化视图的写法。

yangtingkun 评论于: 2007.09.03 22:24
re: 物化视图的快速刷新(一) [回复]

請教:如果FROM语句列表中的所有表,建立是基于PRIMARY KEY类型的物化视图日志,能不能快速刷新?

liuxinfei 评论于: 2007.09.06 09:18
re: 物化视图的快速刷新(一) [回复]

基于主键的物化视图只能用于复制。
也就是说,FROM后面应该是一个表

yangtingkun 评论于: 2007.09.06 09:53
re: 物化视图的快速刷新(一) [回复]

前辈你好,请教一下:如何中断当前正在刷新的物化视图,但是到了下一次刷新时间时仍正常刷新?

在user_jobs中移除了物化视图的刷新任务( dbms_job.remove(631);)之后,物化视图是否从此以后不再进行刷新?除了删除并重建物化之外,还有没有其他方法再将刷新该物化视图的job加入到user_jobs中呢?
谢谢

赤城 评论于: 2008.07.21 10:18
re: 物化视图的快速刷新(一) [回复]

请教一下,我完成刷新物化视图,为什么MLOG不会删除?要怎么查多少个系统在表上建了MLOG~~
我EMAIL:ONGTIM@QQ.COM
麻烦指教一下,感激不尽!

K‘ 评论于: 2008.07.31 17:26
re: 物化视图的快速刷新(一) [回复]

我修正一下上面的,是要怎么查多少个系统在表上建了物化视图~~我采用完全刷新!

K‘ 评论于: 2008.07.31 17:31
re: 物化视图的快速刷新(一) [回复]

TO 赤城:
中断任务只能通过KILL SESSION的方式,JOB运行报错会导致failure增加1,只要FAILURE小于16,JOB会自动重试,如果可以顺利刷新,就不会有问题。

删除了刷新对应的JOB,刷新自然不会再自动执行。可以通过DBMS_JOB.ADD方式将JOB手工添加回来。

yangtingkun 评论于: 2008.08.04 11:28
re: 物化视图的快速刷新(一) [回复]

to K':
物化视图日志可以为多个物化视图服务,并非一个物化视图刷新之后,就会删除物化视图日志中所有的记录。

物化视图日志信息在视图USER_MVIEW_LOGS中
物化视图注册信息在USER_REGISTERED_MVIEWS中
物化视图基表信息在USER_BASE_TABLE_MVIEWS中。

yangtingkun 评论于: 2008.08.04 11:31
re: 物化视图的快速刷新(一) [回复]

To Yangtingkun
创建实体化视图时,文本数据类型长度加倍,为何会这样?

Anthan 评论于: 2009.12.08 16:46
re: 物化视图的快速刷新(一) [回复]

补充上面的,是采用非预建表的方式创建的物化视图

anthan 评论于: 2009.12.08 16:46
re: 物化视图的快速刷新(一) [回复]

两个问题,望博主不吝赐教:

1 物化视图的select中,是否可以包含嵌套查询?

2 oracle文档里有这句话:
The FROM clause of the query can name tables, views, and other materialized views. Collectively these objects are called master tables (a replication term) or detail tables (a data warehousing term)
看这句话的意思,普通视图也是可以做为物化视图的master table的。那如果将普通视图作为欲建立物化视图的一个master table,那这个物化视图怎样实现快速刷新那?因为我发现在普通视图上是不可以建立物化视图日志的。

Wuaner 评论于: 2010.06.30 10:43
re: 物化视图的快速刷新(一) [回复]

1 可以包含嵌套查询,但是嵌套查询会导致物化视图无法快速刷新,解决方法就是建立嵌套的物化视图

2 物化视图的定义中可以包含视图,但是这将导致物化视图无法快速刷新。如果要建立物化视图日志,是建立在视图参考的表上,视图只是定义而已,不过即使建立物化视图日志,物化视图也没有办法快速刷新,不要说视图,就是同义词作为物化视图的基表,也会导致快速刷新失效。

yangtingkun 评论于: 2010.06.30 14:32

发表评论
标题

在此添加评论
表情符号: smile laughing tongue angry crying sad wassat wink

称呼

邮箱地址(可选)

个人主页(可选)

 authimage


切换风格
新闻聚合
博客日历
文章归档...
最新发表...
最新评论...
最多阅读文章...
最多评论文章...
博客统计...
Blog信息
网站链接...