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

下面描述包含聚集的物化视图的快速刷新的限制,并包含了正确设置快速刷新的例子。

可以参考:

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

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


包含聚集的物化视图:

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

2.物化视图查询的所有表必须建立物化视图日志,且物化视图日志必须满足下列限制:

(1)包含物化视图查询语句中的所有列,包括SELECT列表中的列和WHERE语句中的列;

(2)必须指明ROWIDINCLUDING NEW VALUES

(3)如果对基本的操作同时包括INSERTUPDATEDELETE操作(即不是只包含INSERT操作),那么物化视图日志应该包括SEQUENCE

3.允许的聚集函数包括:SUMCOUNTAVGSTDDEVVARIANCEMINMAX

4.必须指定COUNT(*)

5.如果指明了除COUNT之外的聚集函数,则COUNT(expr)也必须存在;

比如:包含SUM(a),则必须同时包含COUNT(a)

6.如果指明了VARIANCE(expr)STDDEV(expr),除了COUNT(expr)外,SUM(expr)也必须指明;

Oracle推荐同时包括SUM(expr*expr)

7.SELECT列表中必须包括所有的GROUP BY列;

8.当物化视图属于下面的某种情况,则快速刷新只支持常规DML插入和直接装载,这种类型的物化视图又称为INSERT-ONLY物化视图;

物化视图包含MINMAX聚集函数;

物化视图包含SUM(expr),但是没有包括COUNT(expr)

物化视图没有包含COUNT(*)

注意:如果建立了这种物化视图且刷新机制是ON COMMIT的,则会存在潜在的问题。当出现了UPDATEDELETE语句,除非手工完全刷新解决这个问题,否则物化视图至此以后都不再自动刷新,且不会报任何错误。

9.如果包含inline viewsouter joinsself joinsgrouping set,则兼容性的设置必须在9.0以上;

10.如果物化视图建立在视图或子查询上,则要求视图必须可以完全合并的。

11.如果没有外连接,则对WHERE语句没有限制。如果包含外连接,则要求WHERE语句只能包括AND连接和“=”操作。对于包含外连接的聚集物化视图,快速刷新支持outer表的修改。且inter表的连接列上必须存在唯一约束。

12.对于包含了ROLLUPCUBEGROUPING SET的物化视图必须满足下列限制条件:

SELECT语句列表中应该包含GROUPING标识符:可以是GROUP BY表达式中所有列的GROUPING_ID函数,也可以是GROUP BY表达式中每一列的GROUPING函数;

例如:GROUP BY语句为:GROUP BY CUBE(a, b),则SELECT列表应该包括GROUPING_ID(a, b)或者GROUPING(a)GROUPING(b)

GROUP BY不能产生重复的GROUPING

比如:GROUP BY a, ROLLUP(a, b)则不支持快速刷新,因为包含了重复的GROUPING(a), (a, b), (a)

首先,建立一个只包含聚集操作的满足快速刷新条件的例子,然后建立一个同时包括聚集和连接操作的例子。

最后依次违反上述11个条件,分别测试,查看会出现什么错误。(第一种约束条件是所有物化视图都必须满足的条件,在文章物化视图的快速刷新(一)中已经进行了说明,这里就不再重复描述了)。

首先,创建测试环境:

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;

已创建48行。

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

已创建48行。

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

已创建48行。

SQL> commit;

提交完成。

建立可以成功快速刷新的例子,这个物化视图只包含聚集:

SQL> create materialized view log on fact with rowid, sequence (aid, num)
2 including new values;

实体化视图日志已创建。

SQL> create materialized view mv_fact refresh fast on commit as
2 select aid, count(*) count, count(num) count_num, sum(num) sum_num
3 from fact group by aid;

实体化视图已创建。

建立快速刷新的例子,物化视图包含聚集和连接:

SQL> drop materialized view mv_fact;

实体化视图已删除。

SQL> drop materialized view log on fact;

实体化视图日志已删除。

SQL> create materialized view log on fact with rowid, sequence (aid, num)
2 including new values;

实体化视图日志已创建。

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

实体化视图日志已创建。

SQL> create materialized view mv_fact refresh fast on commit as
2 select name, count(*) count, count(num) count_num, sum(num) sum_num
3 from fact, dim_a where aid = dim_a.id group by name;

实体化视图已创建。

接着,依次违反聚集物化视图快速刷新的每一个限制,检查出现的错误信息:

2.物化视图查询的所有表必须建立物化视图日志,且物化视图日志必须满足下列限制:

(1)包含物化视图查询语句中的所有列,包括SELECT列表中的列和WHERE语句中的列;

(2)必须指明ROWIDINCLUDING NEW VALUES

(3)如果对基表的操作同时包括INSERTUPDATEDELETE操作(即不是只包含INSERT操作),那么物化视图日志应该包括SEQUENCE

SQL> drop materialized view mv_fact;

实体化视图已删除。

SQL> drop materialized view log on fact;

实体化视图日志已删除。

SQL> create materialized view mv_fact refresh fast on commit as
2 select aid, count(*) count, count(num) count_num, sum(num) sum_num
3 from fact group by aid;
from fact group by aid
*
ERROR
位于第 3 :
ORA-23413:
"YANGTK"."FACT" 不带实体化视图日志

SQL> create materialized view log on fact with rowid, sequence (aid, num)
2 including new values;

实体化视图日志已创建。

SQL> create materialized view mv_fact_error refresh fast on commit as
2 select aid, count(*) count, count(num) count_num, sum(num) sum_num,
3 count(bid) count_b from fact group by aid;
count(bid) count_b from fact group by aid
*
ERROR
位于第 3 :
ORA-12033:
不能使用 "YANGTK"."FACT" 上实体化视图日志中的过滤器列


SQL> create materialized view mv_fact_error refresh fast on commit as
2 select aid, count(*) count, count(num) count_num, sum(num) sum_num
3 from fact where bid = 5 group by aid;
from fact where bid = 5 group by aid
*
ERROR
位于第 3 :
ORA-12033:
不能使用 "YANGTK"."FACT" 上实体化视图日志中的过滤器列

SQL> drop materialized view log on fact;

实体化视图日志已删除。

SQL> create materialized view log on fact with rowid, sequence (aid, num);

实体化视图日志已创建。

SQL> create materialized view mv_fact refresh fast on commit as
2 select aid, count(*) count, count(num) count_num, sum(num) sum_num
3 from fact group by aid;
from fact group by aid
*
ERROR
位于第 3 :
ORA-32401: "YANGTK"."FACT"
上的实体化视图日志没有新值

SQL> drop materialized view log on fact;

实体化视图日志已删除。

SQL> drop materialized view log on dim_a;

实体化视图日志已删除。

SQL> create materialized view log on fact with rowid, sequence (aid, num)
2 including new values;

实体化视图日志已创建。

SQL> create materialized view log on dim_a with primary key, sequence (name)
2 including new values;

实体化视图日志已创建。

SQL> create materialized view mv_fact refresh fast on commit as
2 select name, count(*) count, count(num) count_num, sum(num) sum_num
3 from fact, dim_a where aid = dim_a.id group by name;
from fact, dim_a where aid = dim_a.id group by name
*
ERROR
位于第 3 :
ORA-12032:
不能使用 "YANGTK"."DIM_A" 上实体化视图日志中的 rowid

SQL> drop materialized view log on fact;

实体化视图日志已删除。

SQL> drop materialized view log on dim_a;

实体化视图日志已删除。

SQL> create materialized view log on fact with rowid (aid, num)
2 including new values;

实体化视图日志已创建。

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

实体化视图日志已创建。

SQL> create materialized view mv_fact refresh fast on commit as
2 select name, count(*) count, count(num) count_num, sum(num) sum_num
3 from fact, dim_a where aid = dim_a.id group by name;

实体化视图已创建。

SQL> truncate table mv_capabilities_table;

表已截掉。

SQL> begin
2 dbms_mview.explain_mview('select name, count(*) count, count(num) count_num, sum(num) sum_num
3 from fact, dim_a where aid = dim_a.id group by name');
4 end;
5 /

PL/SQL 过程已成功完成。

SQL> select capability_name, possible, msgtxt from mv_capabilities_table
2 where capability_name like 'REFRESH%';

CAPABILITY_NAME P MSGTXT
------------------------------ - -----------------------------
REFRESH_COMPLETE Y
REFRESH_FAST Y
REFRESH_FAST_AFTER_INSERT Y
REFRESH_FAST_AFTER_ONETAB_DML Y
REFRESH_FAST_AFTER_ANY_DML N mv
日志没有序列号
REFRESH_FAST_AFTER_ANY_DML N mv
日志没有序列号
REFRESH_FAST_PCT N PCT
不可能在实体化视图中的任何从表上

已选择7行。

SQL> select * from mv_fact;

NAME COUNT COUNT_NUM SUM_NUM
------------------------------ ---------- ---------- ----------
a1 7 7
420a2 9 9 450a3 9 9 468a4 9 9 486a5 8 8 400a6 8 8 416

已选择6行。

SQL> insert into fact values (100, 1, 1, 1000);

已创建 1 行。

SQL> update dim_a set name = 'a1a' where id = 1;

已更新 1 行。

SQL> commit;

提交完成。

SQL> select * from mv_fact;

NAME COUNT COUNT_NUM SUM_NUM
------------------------------ ---------- ---------- ----------
a2 9 9
450a3 9 9 468a4 9 9 486a5 8 8 400a6 8 8 416a1a 8 8 1420

已选择6行。

SQL> update dim_a set name = 'a1' where name = 'a1a';

已更新 1 行。

SQL> update fact set aid = 7 where aid = 1;

已更新8行。

SQL> update fact set aid = 1 where aid = 2;

已更新9行。

SQL> update dim_a set name = 'a2a' where name = 'a2';

已更新 1 行。

SQL> update fact set aid = 2 where aid = 7;

已更新8行。

SQL> delete fact where num = 1000;

已删除 1 行。

SQL> commit;

提交完成。

SQL> select * from mv_fact;

NAME COUNT COUNT_NUM SUM_NUM
------------------------------ ---------- ---------- ----------
a2 9 9
450a3 9 9 468a4 9 9 486a5 8 8 400a6 8 8 416a1a 8 8 1420

已选择6行。

SQL> exec dbms_mview.refresh('MV_FACT');
BEGIN dbms_mview.refresh('MV_FACT'); END;

*
ERROR
位于第 1 :
ORA-12057:
实体化视图 "YANGTK"."MV_FACT" 无效, 必须进行完全刷新

ORA-06512:
"SYS.DBMS_SNAPSHOT", line 794
ORA-06512:
"SYS.DBMS_SNAPSHOT", line 851
ORA-06512:
"SYS.DBMS_SNAPSHOT", line 832
ORA-06512:
line 1


SQL> exec dbms_mview.refresh('MV_FACT', 'C')

PL/SQL 过程已成功完成。

对于包含对多表的UPDATE/DELETE/INSERT混合操作的物化视图,只有建立物化视图日志的时候指定SEQUENCE才能保证快速刷新。

3.允许的聚集函数包括:SUMCOUNTAVGSTDDEVVARIANCEMINMAX

SQL> create materialized view log on fact with rowid, sequence (aid, num)
2 including new values;

实体化视图日志已创建。

SQL> create materialized view mv_fact_err refresh fast on commit as
2 select aid, count(*) count, count(num) count_num, sum(num) sum_num,
3 stddev_pop(num) std_num
4 from fact group by aid;
from fact group by aid
*
ERROR
位于第 4 :
ORA-12054:
无法为实体化视图设置 ON COMMIT 刷新属性


SQL> create materialized view mv_fact_err refresh fast as
2 select aid, count(*) count, count(num) count_num, sum(num) sum_num,
3 stddev_pop(num) std_num
4 from fact group by aid;
from fact group by aid
*
ERROR
位于第 4 :
ORA-12015:
不能从复杂查询中创建一个可快速刷新的实体化视图


SQL> begin
2 dbms_mview.explain_mview('select aid, count(*) count, count(num) count_num, sum(num) sum_num,
3 stddev_pop(num) std_num
4 from fact group by aid');
5 end;
6 /

PL/SQL 过程已成功完成。

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

MSGTXT
-------------------------------------------------------
表达式中聚集函数嵌套

上面的例子包含了其他聚集函数STDDEV_P0P(expr),因此无法进行快速刷新。

4.必须指定COUNT(*)

SQL> create materialized view mv_fact_err refresh fast on commit as
2 select aid, count(num) count_num, sum(num) sum_num
3 from fact group by aid;

实体化视图已创建。

SQL> begin
2 dbms_mview.explain_mview('select aid, count(num) count_num, sum(num) sum_num
3 from fact group by aid');
4 end;
5 /

PL/SQL 过程已成功完成。

SQL> select capability_name, possible, msgtxt from mv_capabilities_table
2 where capability_name like 'REFRESH%';

CAPABILITY_NAME P MSGTXT
------------------------------ - ----------------------------------
REFRESH_COMPLETE Y
REFRESH_FAST Y
REFRESH_FAST_AFTER_INSERT Y
REFRESH_FAST_AFTER_ONETAB_DML N
在选择列表中不存在 COUNT(*)
REFRESH_FAST_AFTER_ANY_DML N
查看禁用 REFRESH_FAST_AFTER_ONETAB_DML 的原因

REFRESH_FAST_PCT N PCT
不可能在实体化视图中的任何从表上

已选择6行。

不加COUNT(*),建立快速刷新的物化视图居然成功了,通过执行EXPLAIN_MVIEW过程,可以发现,由于确实COUNT(*)对于INSERT操作是可以快速刷新的,不过对于UPDATEDELETE则会造成快速刷新的失败。

SQL> select * from mv_fact_err;

AID COUNT_NUM SUM_NUM
---------- ---------- ----------
1 8 432
2 8 352
3 8 368
4 8 384
5 8 400
6 8 416

已选择6行。

SQL> insert into fact values (100, 1, 2, 1000);

已创建 1 行。

SQL> commit;

提交完成。

SQL> select * from mv_fact_err;

AID COUNT_NUM SUM_NUM
---------- ---------- ----------
1 9 1432
2 8 352
3 8 368
4 8 384
5 8 400
6 8 416

已选择6行。

SQL> delete fact where id = 100;

已删除 1 行。

SQL> commit;

提交完成。

SQL> select * from mv_fact_err;

AID COUNT_NUM SUM_NUM
---------- ---------- ----------
1 9 1432
2 8 352
3 8 368
4 8 384
5 8 400
6 8 416

已选择6行。

SQL> exec dbms_mview.refresh('MV_FACT_ERR')
BEGIN dbms_mview.refresh('MV_FACT_ERR'); END;

*
ERROR
位于第 1 :
ORA-12057:
实体化视图 "YANGTK"."MV_FACT_ERR" 无效, 必须进行完全刷新

ORA-06512:
"SYS.DBMS_SNAPSHOT", line 794
ORA-06512:
"SYS.DBMS_SNAPSHOT", line 851
ORA-06512:
"SYS.DBMS_SNAPSHOT", line 832
ORA-06512:
line 1

SQL> exec dbms_mview.refresh('MV_FACT_ERR', 'C')

PL/SQL 过程已成功完成。

SQL> select * from mv_fact_err;

AID COUNT_NUM SUM_NUM
---------- ---------- ----------
1 8 432
2 8 352
3 8 368
4 8 384
5 8 400
6 8 416

已选择6行。

对于ON COMMIT的物化视图要注意,这种情况将造成无法快速刷新,且不会报任何错误,除非你手工执行完全刷新,否则物化视图中的数据无法继续保持同步。

5.如果指明了除COUNT之外的聚集函数,则COUNT(expr)也必须存在;

比如:包含SUM(a),则必须同时包含COUNT(a)

SQL> create materialized view mv_fact_err refresh fast on commit as
2 select aid, count(*) count, sum(num) sum_num
3 from fact group by aid;

实体化视图已创建。

SQL> select * from mv_fact_err;

AID COUNT SUM_NUM
---------- ---------- ----------
1 9 1432
2 8 352
3 8 368
4 8 384
5 8 400
6 8 416

已选择6行。

SQL> insert into fact values (101, 2, 2, 1000);

已创建 1 行。

SQL> commit;

提交完成。

SQL> select * from mv_fact_err;

AID COUNT SUM_NUM
---------- ---------- ----------
1 9 1432
2 9 1352
3 8 368
4 8 384
5 8 400
6 8 416

已选择6行。

SQL> delete fact where id = 101;

已删除 1 行。

SQL> commit;

提交完成。

SQL> select * from mv_fact_err;

AID COUNT SUM_NUM
---------- ---------- ----------
1 9 1432
2 9 1352
3 8 368
4 8 384
5 8 400
6 8 416

已选择6行。

SQL> exec dbms_mview.refresh('MV_FACT_ERR');
BEGIN dbms_mview.refresh('MV_FACT_ERR'); END;

*
ERROR
位于第 1 :
ORA-12057:
实体化视图 "YANGTK"."MV_FACT_ERR" 无效, 必须进行完全刷新

ORA-06512:
"SYS.DBMS_SNAPSHOT", line 794
ORA-06512:
"SYS.DBMS_SNAPSHOT", line 851
ORA-06512:
"SYS.DBMS_SNAPSHOT", line 832
ORA-06512:
line 1


SQL> exec dbms_mview.refresh('MV_FACT_ERR', 'C')

PL/SQL 过程已成功完成。

SQL> begin
2 dbms_mview.explain_mview('select aid, count(*) count, sum(num) sum_num
3 from fact group by aid');
4 end;
5 /

PL/SQL 过程已成功完成。

SQL> select capability_name, possible, msgtxt from mv_capabilities_table
2 where capability_name like 'REFRESH%';

CAPABILITY_NAME P MSGTXT
------------------------------ - -----------------------------------
REFRESH_COMPLETE Y
REFRESH_FAST Y
REFRESH_FAST_AFTER_INSERT Y
REFRESH_FAST_AFTER_ONETAB_DML N
使用 SUM(expr) , 未提供 COUNT(expr)
REFRESH_FAST_AFTER_ANY_DML N
查看禁用 REFRESH_FAST_AFTER_ONETAB_DML 的原因

REFRESH_FAST_PCT N PCT
不可能在实体化视图中的任何从表上

已选择6行。

这个错误的现象和4中的十分相似。

6.如果指明了VARIANCE(expr)STDDEV(expr),除了COUNT(expr)外,SUM(expr)也必须指明;

SQL> drop materialized view mv_fact_err;

实体化视图已删除。

SQL> create materialized view mv_fact refresh fast on commit as
2 select aid, count(*) count, count(num) count_num, sum(num) sum_num,
3 variance(num) var_num
4 from fact group by aid;

实体化视图已创建。

SQL> create materialized view mv_fact_err refresh fast on commit as
2 select aid, count(*) count, count(num) count_num,
3 variance(num) var_num
4 from fact group by aid;
from fact group by aid
*
ERROR
位于第 4 :
ORA-12054:
无法为实体化视图设置 ON COMMIT 刷新属性


SQL> create materialized view mv_fact_err refresh fast as
2 select aid, count(*) count, count(num) count_num,
3 variance(num) var_num
4 from fact group by aid;
from fact group by aid
*
ERROR
位于第 4 :
ORA-12015:
不能从复杂查询中创建一个可快速刷新的实体化视图


SQL> truncate table mv_capabilities_table;

表已截掉。

SQL> begin
2 dbms_mview.explain_mview('select aid, count(*) count, count(num) count_num,
3 variance(num) var_num
4 from fact group by aid');
5 end;
6 /

PL/SQL 过程已成功完成。

SQL> select capability_name, possible, msgtxt from mv_capabilities_table
2 where capability_name like 'REFRESH%';

CAPABILITY_NAME P MSGTXT
------------------------------ - ------------------------------
REFRESH_COMPLETE Y
REFRESH_FAST N
REFRESH_FAST_AFTER_INSERT N agg(expr)
需要相应的 SUM(expr) 函数
REFRESH_FAST_AFTER_ONETAB_DML N
查看禁用 REFRESH_FAST_AFTER_INSERT 的原因
REFRESH_FAST_AFTER_ANY_DML N
查看禁用 REFRESH_FAST_AFTER_ONETAB_DML 的原因
REFRESH_FAST_PCT N PCT
不可能在实体化视图中的任何从表上

已选择6行。

7.SELECT列表中必须包括所有的GROUP BY列;

SQL> create materialized view mv_fact_err refresh fast on commit as
2 select count(*) count, count(num) count_num
3 from fact group by aid;
from fact group by aid
*
ERROR
位于第 3 :
ORA-12054:
无法为实体化视图设置 ON COMMIT 刷新属性


SQL> create materialized view mv_fact_err refresh fast as
2 select count(*) count, count(num) count_num
3 from fact group by aid;
from fact group by aid
*
ERROR
位于第 3 :
ORA-12015:
不能从复杂查询中创建一个可快速刷新的实体化视图


SQL> truncate table mv_capabilities_table;

表已截掉。

SQL> begin
2 dbms_mview.explain_mview('select count(*) count, count(num) count_num
3 from fact group by aid');
4 end;
5 /

PL/SQL 过程已成功完成。

SQL> select capability_name, possible, msgtxt from mv_capabilities_table
2 where capability_name like 'REFRESH%';

CAPABILITY_NAME P MSGTXT
------------------------------ - -----------------------------
REFRESH_COMPLETE Y
REFRESH_FAST N
REFRESH_FAST_AFTER_INSERT N
实体化视图至少忽略了选择列表中的一个分组关键字
REFRESH_FAST_AFTER_ONETAB_DML N
查看禁用 REFRESH_FAST_AFTER_INSERT 的原因
REFRESH_FAST_AFTER_ANY_DML N
查看禁用 REFRESH_FAST_AFTER_ONETAB_DML 的原因
REFRESH_FAST_PCT N PCT
不可能在实体化视图中的任何从表上

已选择6行。

8.当物化视图属于下面的某种情况,则快速刷新只支持常规DML插入和直接装载,这种类型的物化视图又称为INSERT-ONLY物化视图;

物化视图包含MINMAX聚集函数;

物化视图包含SUM(expr),但是没有包括COUNT(expr)

物化视图没有包含COUNT(*)

SQL> create materialized view mv_fact_err refresh fast on commit as
2 select aid, count(*) count, count(num) count_num, max(num) max_num
3 from fact group by aid;

实体化视图已创建。

SQL> SELECT * FROM MV_FACT_ERR;

AID COUNT COUNT_NUM MAX_NUM
---------- ---------- ---------- ----------
1 8 8 96
2 8 8 86
3 8 8 88
4 8 8 90
5 8 8 92
6 8 8 94

已选择6行。

SQL> INSERT INTO FACT VALUES (101, 2, 1, 100);

已创建 1 行。

SQL> COMMIT;

提交完成。

SQL> SELECT * FROM MV_FACT_ERR;

AID COUNT COUNT_NUM MAX_NUM
---------- ---------- ---------- ----------
1 8 8 96
2 9 9 100
3 8 8 88
4 8 8 90
5 8 8 92
6 8 8 94

已选择6行。

SQL> DELETE FACT WHERE ID = 101;

已删除 1 行。

SQL> COMMIT;

提交完成。

SQL> SELECT * FROM MV_FACT_ERR;

AID COUNT COUNT_NUM MAX_NUM
---------- ---------- ---------- ----------
1 8 8 96
3 8 8 88
4 8 8 90
5 8 8 92
6 8 8 94
2 8 8 86

已选择6行。

SQL> UPDATE FACT SET NUM = 95 WHERE NUM = 96;

已更新 1 行。

SQL> COMMIT;

提交完成。

SQL> SELECT * FROM MV_FACT_ERR;

AID COUNT COUNT_NUM MAX_NUM
---------- ---------- ---------- ----------
3 8 8 88
4 8 8 90
5 8 8 92
6 8 8 94
2 8 8 86
1 8 8 95

已选择6行。

SQL> truncate table mv_capabilities_table;

表已截掉。

SQL> begin
2 dbms_mview.explain_mview('select aid, count(*) count, count(num) count_num, max(num) max_num
3 from fact group by aid');
4 end;
5 /

PL/SQL 过程已成功完成。

SQL> select capability_name, possible, msgtxt from mv_capabilities_table
2 where capability_name like 'REFRESH%';

CAPABILITY_NAME P MSGTXT
------------------------------ - ------------------------------
REFRESH_COMPLETE Y
REFRESH_FAST Y
REFRESH_FAST_AFTER_INSERT Y
REFRESH_FAST_AFTER_ONETAB_DML N
实体化视图使用了 MIN MAX 聚集函数
REFRESH_FAST_AFTER_ANY_DML N
查看禁用 REFRESH_FAST_AFTER_ONETAB_DML 的原因
REFRESH_FAST_PCT N PCT
不可能在实体化视图中的任何从表上

已选择6行。

根据测试的结果,发现Oracle的文档描述有些问题,MAXMIN聚集函数是支持单表DML操作的快速刷新的。EXPLAIN_MVIEW过程给出的解释也不完全正确。下面看看包含连接的情况。

SQL> create materialized view mv_fact_err2 refresh fast on commit as
2 select name, count(*) count, count(num) count_num, max(num) max_num
3 from fact, dim_a where aid = dim_a.id group by name;

实体化视图已创建。

SQL> select * from mv_fact_err2;

NAME COUNT COUNT_NUM MAX_NUM
------------------------------ ---------- ---------- ----------
a1 8 8
95a2 8 8 86a3 8 8 88a4 8 8 90a5 8 8 92a6 8 8 94

已选择6行。

SQL> insert into fact values (101, 1, 1, 100);

已创建 1 行。

SQL> commit;

提交完成。

SQL> select * from mv_fact_err2;

NAME COUNT COUNT_NUM MAX_NUM
------------------------------ ---------- ---------- ----------
a1 9 9
100a2 8 8 86a3 8 8 88a4 8 8 90a5 8 8 92a6 8 8 94

已选择6行。

SQL> delete fact where id = 101;

已删除 1 行。

SQL> commit;

提交完成。

SQL> select * from mv_fact_err2;

NAME COUNT COUNT_NUM MAX_NUM
------------------------------ ---------- ---------- ----------
a1 9 9
100a2 8 8 86a3 8 8 88a4 8 8 90a5 8 8 92a6 8 8 94

已选择6行。

由此可见,MAXMIN函数支持只包含聚集不包含连接的物化视图的快速刷新。这种刷新对任意DML操作有效。如果物化视图包含多表连接,则只支持INSERT操作,其他DML操作将导致物化视图的快速刷新失败。

第二、三点前面的测试已经描述过了。

9.如果包含inline viewsouter joinsself joinsgrouping set,则兼容性的设置必须在9.0以上;

SQL> drop materialized view mv_fact_err2;

实体化视图已删除。

SQL> drop materialized view mv_fact;

实体化视图已删除。

SQL> drop materialized view mv_fact_err;

实体化视图已删除。

SQL> drop materialized view log on fact;

实体化视图日志已删除。

SQL> create materialized view log on fact with rowid, sequence (id, aid, bid, num)
2 including new values;

实体化视图日志已创建。

yangtingkun 发表于:2005.01.28 17:23 ::分类: ( ORACLE ) ::阅读:(12056次) :: 评论 (22)
第一次自己回复 [回复]

居然没有贴全,郁闷。

yangtingkun 评论于: 2005.12.07 14:27
向您请教一个问题 [回复]

CREATE MATERIALIZED VIEW ANALYZE.GOODSACCT_MV
TABLESPACE BBGLG
PARALLEL
PARTITION BY RANGE (Month)
(PARTITION P2005 VALUES LESS THAN ('200501'),
PARTITION P20051 VALUES LESS THAN ('200507'),
PARTITION P20052 VALUES LESS THAN ('200601'),
PARTITION P20061 VALUES LESS THAN ('200607'),
PARTITION P20062 VALUES LESS THAN ('200701'),
PARTITION P20071 VALUES LESS THAN ('200707'),
PARTITION P20072 VALUES LESS THAN ('200801'),

)
BUILD DEFERRED
REFRESH FAST WITH ROWID
ON COMMIT
ENABLE QUERY REWRITE
AS
select
Month
,ScateID
,McateID
,LcateID
,SOrgID
,MOrgID
,Grouping_ID(Month,ScateID,McateID,LCateID,SOrgID,MOrgID) Gid
,sum(TransQty) as TransQty
,sum(TransQty*TransPrice) as TransSum
,sum(TransQty*(TransPrice-CostPrice)) as ProfitSum
,sum(TransQty*(UNIONSALEPRICE-NORMALSALEPRICE)) as PriceDiscount
,sum(TransQty*(NORMALSALEPRICE-TransPrice)) as PmtDiscount
,count(TransQty) as c_TransQty
,count(TransQty*TransPrice) as c_TransSum
,count(TransQty*(TransPrice-CostPrice)) as c_ProfitSum
,count(TransQty*(UNIONSALEPRICE-NORMALSALEPRICE)) as c_PriceDiscount
,count(TransQty*(NORMALSALEPRICE-TransPrice)) as c_PmtDiscount
,count(*) as cnt
from Times T,Category_T C,Organization_T O,GoodsAcct G
where (G.TransDate=T.Day)
and (G.shopid=O.Sorgid)
and (G.cateid=C.SCateid)
group by
Month
,Rollup(ScateID,McateID,LcateID)
,Rollup(SOrgID,MOrgID)
我这个物化视图为什么不能快速刷新,(注:如果没有分区的那段只有select 段可以实现快速刷新)谢谢

xieren 评论于: 2005.12.21 14:58
[回复]

把你完整的信息贴到论坛里面吧,这里回答问题不方便

yangtingkun 评论于: 2005.12.22 11:00
回复 [回复]

您好,我没有在论坛中发,因为要发的相关内容太多。还是向您请教一个问题:要创建分区的物化视图有什么要求或条件?对基表有什么要求?我已经拜读了您Blog中所有的文章,没有找到分区物化视图(视图中包括rollup)相关文章

xieren 评论于: 2005.12.22 16:19
[回复]

个人认为,物化视图是否分区应该和物化视图是否可以快速刷新没有关系

yangtingkun 评论于: 2005.12.22 23:24
回复 [回复]

谢谢,确如您所说,我已经解决了这个问题。

xieren 评论于: 2005.12.23 10:37
回复 [回复]

不过分区与快速刷新还是有一点关系的,如果用了grouping_ID, rollup ,要支持快速刷新也要根据grouping_ID的值来建子分区,不然不行,我也不知道是不是自己搞错了还是什么的,反正如果我只按month来分区,不在其下建Grouping_ID子分区,视图就是不支持快速刷新。
再向您请教一下这个grouping_ID的算法是怎样的?我看了一些书都说是什么矢量运算。

xieren 评论于: 2005.12.23 10:51
[回复]

我用你贴出来的物化视图的创建语句大致测试了一下,没有发现分区对快速刷新有什么影响。
如果你还存在问题,我建议你将你完整的环境贴到论坛里面。

yangtingkun 评论于: 2006.01.11 17:54
re: 物化视图的快速刷新(二) [回复]

这句话有问题“MAX和MIN聚集函数是支持单表DML操作的快速刷新的。”
例如t1(tc1) 值(1,2,3)
物化视图v1 as select count(tc1),min(tc1) from t1;
从t1中删除2或3对快速刷新是没有影响的,但是如果从t1中删除1就不能快速刷新只能完全刷新了。

11_小毅 评论于: 2008.04.02 17:35
re: 物化视图的快速刷新(二) [回复]

你写的这种SQL本来就不满足快速包含聚集操作的快速刷新条件。

这篇文章讨论的物化视图需要包含GROUP BY,而你的例子不符合这篇文章最基表要求。

yangtingkun 评论于: 2008.04.11 10:44
请教:只读物化视图不能自动刷新 [回复]

CREATE MATERIALIZED VIEW LOG ON "usr1"."T1"
TABLESPACE "SYSTEM"
WITH PRIMARY KEY
EXCLUDING NEW VALUES;

CREATE MATERIALIZED VIEW "usr2"."T1"
REFRESH FAST
AS SELECT * FROM "usr1"."T1"@TESTCOM.SERVICE.COM;

这是脚本中的两段话,整个脚本执行完成后,发现试图站点数据不能自动更新,要以manuanl方式更新才可以,如果没有人为干预,那自动刷新就一直失败,知道16次后变成broken,这究竟是什么原因呢?

数据库环境是9i,参考文档是Advanced Replication Management API Reference.pdf和Advanced.Replication.Research.by.Kamus.pdf

都查了好几天了,快崩溃了。。。

dragman 评论于: 2008.05.13 17:57
re: 物化视图的快速刷新(二) [回复]

斑竹阿,你怎么不现身呢。。。

dragman 评论于: 2008.05.13 23:42
re: 物化视图的快速刷新(二) [回复]

斑竹终于现身了,经过这几天的观察思考和实验,我怀疑是由于db_domain的设置引起的,开始时候作为materliazed view的数据库没有设置db_domain。

但是现在竟数据库加上db_domain并且和marster一样,则脚本执行到
BEGIN
DBMS_REPCAT.CREATE_MVIEW_REPGROUP (
GNAME => 'SITESTGRP',
MASTER => 'TESTCOM.SERVICE.COM',
PROPAGATION_MODE => 'ASYNCHRONOUS');
END;
/
这里,会有如下错误
BEGIN
*
ERROR 位于第 1 行:
ORA-04052: error occurred when looking up remote object
PROXY_MVIEWADMIN.SYS@JDPRDCOM.GEMSHMES.COM
ORA-00604: error occurred at recursive SQL level 2
ORA-12154: TNS:could not resolve service name
ORA-06512: at "SYS.DBMS_REPCAT_UTL", line 4262
ORA-06512: at "SYS.DBMS_REPCAT_SNA_UTL", line 1698
ORA-06512: at "SYS.DBMS_REPCAT_SNA", line 64
ORA-06512: at "SYS.DBMS_REPCAT", line 1262
ORA-06512: at line 2
我猜是由于增加了db_domain后引起的,可是为什么这时候用client或者slqplus都能连通呢?

dragman 评论于: 2008.05.15 15:46
re: 物化视图的快速刷新(二) [回复]

对了,在没有增加db_domain以前,察看error log如下
file /oracle/admin/spcrpt/bdump/spcrpt_j004_7694.trc: ORA-12012: error on auto execute of job 35 ORA-12154: TNS:could not resolve service name ORA-06512: at "SYS.DBMS_SNAPSHOT", line 803 ORA-06512: at "SYS.DBMS_SNAPSHOT", line 860 ORA-06512: at "SYS.DBMS_IREFRESH", line 683 ORA-06512: at "SYS.DBMS_REFRESH", line 195 ORA-06512: at line 1

dragman 评论于: 2008.05.15 15:57
re: 物化视图的快速刷新(二) [回复]

对了,还有一个线索,虽然脚本执行到这里才出错,但是
select sysdate from dual@dblinkname
的时候也会出错说无法解析tns名字,可是dblink明明建好了
是用mviewadmin来连接的

不过我看这个数据库有另一个叫mvadmin的用户,不知道谁见的,从名字上判断和我这个在做同样的事情,会不会有冲突呢?

dragman 评论于: 2008.05.15 16:14
re: 物化视图的快速刷新(二) [回复]

你给的那个连接我看了,在建立mviewadmin这个用户的dblink的时候,指定了user的,其实我不是dba,只是现在要用的replication这个机制,所以直接找文档copy下来的脚本,参考文档就是我前面提到的,有一篇应该还是您的大作!
呵呵

dragman 评论于: 2008.05.15 16:16
re: 物化视图的快速刷新(二) [回复]

发现所有的的dblink都不通

不好意思,斑竹,我们schedule已经因为这个严重delay了,急啊,所以垃圾留言可能多了点,您看到后可以酌情删掉一点,不好意思

dragman 评论于: 2008.05.15 16:31
re: 物化视图的快速刷新(二) [回复]

问题解决,是因为加了db_domain后,listener.oar文件没有修改造成的,修改此文件,加上域名,充气数据库后成功,哈哈

dragman 评论于: 2008.05.16 10:41
re: 物化视图的快速刷新(二) [回复]

请问杨版主能加下我MSN吗
koko_24_i@hotmail.com

请教个问题
如果查询语句中的group by和MV中的group by不能完全匹配
比如 少个列 或者顺序不一样
还能够查询重用吗

koko 评论于: 2008.05.16 15:25
re: 物化视图的快速刷新(二) [回复]

斑竹,按照你的大作《Advanced.Replication.Research.by.Kamus.pdf》我再添加索引的时候出错。具体就是这句话

BEGIN
DBMS_REPCAT.CREATE_MVIEW_REPOBJECT (
gname => 'GRP01',
sname => 'user',
oname => 'index_table_001',
type => 'INDEX',
min_communication => TRUE);
END;
错误内容是
ora-23355 object does not exist or is invalid at master

前面这句话倒是没错
BEGIN
DBMS_REPCAT.CREATE_MASTER_REPOBJECT (
gname => 'GRP01',
type => 'INDEX',
oname => 'INDEX_TABLE-001',
sname => 'USER1',
use_existing_object => TRUE,
copy_rows => FALSE);
END;

我查过了,没有拼写错误,对USER1是可见的,那还有什么云因回导致这个结果呢?

dragman 评论于: 2008.05.19 19:52
re: 物化视图的快速刷新(二) [回复]

to dragman
建立了物化视图之后,如果没有必要,不要修改DOMAIN或GLOBALNAME,否则可能导致所有的数据库链都不可用。

另外,最后一个错误没有看明白你的意思。
不过可以提示你的是,注意大小写,注意USER本身是Oracle的关键字,很可能需要添加双引号

yangtingkun 评论于: 2008.05.20 11:06
re: 物化视图的快速刷新(二) [回复]

to koko
group by中字段的顺序对应查询重写没有影响。
如果物化视图创建语句中GROUP BY的字段包含查询语句中GROUP BY的字段,那么这个查询就可能使用物化视图。

但是有些结果是得到的,比如AVG/COUNT(DISTINCT)等等

yangtingkun 评论于: 2008.05.20 11:19

发表评论
标题

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

称呼

邮箱地址(可选)

个人主页(可选)

 authimage


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