不少人大概和我一样在创建物化视图的时候会犯头痛,怎样合理的改写SQL语句以及添加物化视图日志需要经过慎重精密的考虑。有了DBMS_ADVISOR.TUNE_MVIEW存储过程这个帮手后,极大地方便了DBA或应用设计人员创建和优化物化视图。该TUNE_MVIEW存储过程可以做到优化物化视图中的查询定义,修正物化视图日志的问题,此外它还能为原先不能refresh fast的物化视图提出建议以使得其可以快速刷新。
针对那些确实无法快速刷新的复杂查询,TUNE_MVIEW过程也可能给出将一个查询分解为多个物化视图达到快速刷新和查询重写的目的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
SQL>
CREATE
MATERIALIZED
VIEW
MACLEAN.STRMTS
2 USING
INDEX
REFRESH FAST
ON
DEMAND
3 ENABLE QUERY REWRITE
4
AS
select
distinct
t1,t2
from
MACLEAN.strb;
AS
select
distinct
t1,t2
from
MACLEAN.strb
*
ERROR
at
line 4:
ORA-12015: cannot
create
a fast refresh materialized
view
from
a complex query
/* 以
select
distinct
查询语句为例,该语句本身不符合refresh fast的标准,但TUNE_MVIEW存储过程
可以将这种查询变形使得满足快速刷新的条件 */
-- PROCEDURE DBMS_ADVISOR.TUNE_MVIEW
-- PURPOSE: Tune a Create Materialized View statement to
-- ADVISOR SUPPORT: SQL Access Advisor
-- PARAMETERS:
-- TASK_NAME
-- The user can pass in a user-defined task name or
-- get a returned system-generated task name.
-- MV_CREATE_STMT
-- CREATE MATERIALIZED VIEW SQL statement to tune
procedure
tune_mview (task_name
in
out
varchar2,
mv_create_stmt
in
clob);
SQL>
set
serveroutput
on
;
SQL>
declare
2 tn varchar2(200);
3
begin
4 DBMS_ADVISOR.TUNE_MVIEW(tn,
5 mv_create_stmt =>
'CREATE MATERIALIZED VIEW MACLEAN.STRMTS
6 USING INDEX REFRESH FAST ON DEMAND
7 ENABLE QUERY REWRITE
8 AS select distinct t1,t2 from MACLEAN.strb'
);
9 dbms_output.put_line(tn);
10
end
;
11 /
TASK_484
PL/SQL
procedure
successfully completed.
SQL>
select
script_type,statement
2
from
dba_tune_mview
3
where
task_name =
'TASK_484'
4
order
by
action_id;
SCRIPT_TYPE STATEMENT
IMPLEMENTATION
CREATE
MATERIALIZED
VIEW
LOG
ON
"MACLEAN"
.
"STRB"
WITH
ROWID,
SEQUENCE
(
"T1"
,
"T2"
) INCLUDING NEW
VALUES
IMPLEMENTATION
ALTER
MATERIALIZED
VIEW
LOG
FORCE
ON
"MACLEAN"
.
"STRB"
ADD
ROWID,
SEQUENCE
(
"T1"
,
"T2"
) INCLUDING NEW
VALUES
IMPLEMENTATION
CREATE
MATERIALIZED
VIEW
MACLEAN.STRMTS USING
INDEX
REFRESH FAST
WITH
ROWID ENABLE QUERY REWRITE
AS
SELECT
MACLEAN.STRB.T2 C1, MACLEAN.STRB.T1 C2,
COUNT
(*) M1
FROM
MACLEAN.STRB
GROUP
BY
MACLEAN.STRB.T2, MACLEAN.STRB.T1
UNDO
DROP
MATERIALIZED
VIEW
MACLEAN.STRMTS
/* 可以看到TUNE_MVIEW存储过程将原查询变形为
SELECT
...
GROUP
BY
的形式 */
SQL>
CREATE
MATERIALIZED
VIEW
LOG
ON
"MACLEAN"
.
"STRB"
WITH
ROWID,
SEQUENCE
(
"T1"
,
"T2"
) INCLUDING NEW
VALUES
;
Materialized
view
log created.
SQL>
ALTER
MATERIALIZED
VIEW
LOG
FORCE
ON
"MACLEAN"
.
"STRB"
ADD
ROWID,
SEQUENCE
(
"T1"
,
"T2"
) INCLUDING NEW
VALUES
;
Materialized
view
log altered.
SQL>
CREATE
MATERIALIZED
VIEW
MACLEAN.STRMTS USING
INDEX
REFRESH FAST
WITH
ROWID
ENABLE QUERY REWRITE
AS
SELECT
MACLEAN.STRB.T2 C1, MACLEAN.STRB.T1 C2,
COUNT
(*) M1
FROM
MACLEAN.STRB
GROUP
BY
MACLEAN.STRB.T2, MACLEAN.STRB.T1;
Materialized
view
created.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
SQL>
CREATE
MATERIALIZED
VIEW
MACLEAN.STRMTD
2 USING
INDEX
REFRESH FAST
3
ON
DEMAND ENABLE QUERY REWRITE
AS
4
select
t2,t3,
count
(*)
from
strc
group
by
t2,t3
5
union
all
6
select
t2,t3,
count
(*)
from
strd
group
by
t2,t3;
select
t2,t3,
count
(*)
from
strd
group
by
t2,t3
*
ERROR
at
line 6:
ORA-12015: cannot
create
a fast refresh materialized
view
from
a complex query
SQL>
set
serveroutput
on
;
SQL>
declare
2 tn varchar2(200);
3
begin
4 DBMS_ADVISOR.TUNE_MVIEW(tn,
5 mv_create_stmt =>
'CREATE MATERIALIZED VIEW MACLEAN.STRMTC
6 USING INDEX REFRESH FAST
7 ON DEMAND ENABLE QUERY REWRITE AS
8 select t2,t3,count(*) from strc group by t2,t3
9 union all
10 select t2,t3,count(*) from strd group by t2,t3'
);
11 dbms_output.put_line(tn);
12
end
;
13 /
TASK_547
PL/SQL
procedure
successfully completed.
SQL>
select
statement
2
from
dba_tune_mview
3
where
task_name =
'TASK_547'
4
order
by
action_id;
CREATE
MATERIALIZED
VIEW
LOG
ON
"MACLEAN"
.
"STRC"
WITH
ROWID,
SEQUENCE
(
"T2"
,
"T3"
) INCLUDING NEW
VALUES
ALTER
MATERIALIZED
VIEW
LOG
FORCE
ON
"MACLEAN"
.
"STRC"
ADD
ROWID,
SEQUENCE
(
"T2"
,
"T3"
) INCLUDING NEW
VALUES
CREATE
MATERIALIZED
VIEW
LOG
ON
"MACLEAN"
.
"STRD"
WITH
ROWID,
SEQUENCE
(
"T2"
,
"T3"
) INCLUDING NEW
VALUES
ALTER
MATERIALIZED
VIEW
LOG
FORCE
ON
"MACLEAN"
.
"STRD"
ADD
ROWID,
SEQUENCE
(
"T2"
,
"T3"
) INCLUDING NEW
VALUES
CREATE
MATERIALIZED
VIEW
MACLEAN.STRMTC$SUB1 USING
INDEX
REFRESH FAST
WITH
ROWID
ON
COMMIT
ENABLE QUERY REWRITE
AS
SELECT
MACLEAN.STRC.T3 C1, MACLEAN.STRC.T2 C2,
COUNT
(*) M1
FROM
MACLEAN.STRC
GROUP
BY
MACLEAN.STRC.T3, MACLEAN.STRC.T2
DROP
MATERIALIZED
VIEW
MACLEAN.STRMTC$SUB1
CREATE
MATERIALIZED
VIEW
MACLEAN.STRMTC$SUB2 USING
INDEX
REFRESH FAST
WITH
ROWID
ON
COMMIT
ENABLE QUERY REWRITE
AS
SELECT
MACLEAN.STRD.T3 C1, MACLEAN.STRD.T2 C2,
COUNT
(*) M1
FROM
MACLEAN.STRD
GROUP
BY
MACLEAN.STRD.T3, MACLEAN.STRD.T2
DROP
MATERIALIZED
VIEW
MACLEAN.STRMTC$SUB2
CREATE
MATERIALIZED
VIEW
MACLEAN.STRMTC USING
INDEX
REFRESH
FORCE
WITH
ROWID ENABLE QUERY REWRITE
AS
(
SELECT
"STRMTC$SUB1"
.
"C2"
"T2"
,
"STRMTC$SUB1"
.
"C1"
"T3"
,
"STRMTC$SUB1"
.
"M1"
"COUNT(*)"
FROM
"MACLEAN"
.
"STRMTC$SUB1"
"STRMTC$SUB1"
)
UNION
ALL
(
SELECT
"STRMTC$SUB2"
.
"C2"
"T2"
,
"STRMTC$SUB2"
.
"C1"
"T3"
,
"STRMTC$SUB2"
.
"M1"
"COUNT(*)"
FROM
"MACLEAN"
.
"STRMTC$SUB2"
"STRMTC$SUB2"
)
DROP
MATERIALIZED
VIEW
MACLEAN.STRMTC
DBMS_ADVANCED_REWRITE.BUILD_SAFE_REWRITE_EQUIVALENCE (
'MACLEAN.STRMTC$RWEQ'
,
'select t2,t3,count(*) from strc group by t2,t3
union all
select t2,t3,count(*) from strd group by t2,t3'
,
' (SELECT "STRMTC$SUB1"."C2" "T2","STRMTC$SUB1"."C1" "T3","STRMTC$SUB1"."M1" "COUNT(*)" FROM "MACLEAN"."STRMTC$SUB1" "STRMTC$SUB1") UNION ALL (SELECT "STRMTC$SUB2"."C2" "T2","STRMTC$SUB2"."C1" "T3","STRMTC$SUB2"."M1" "COUNT(*)" FROM "MACLEAN"."STRMTC$SUB2" "STRMTC$SUB2")'
,600916906)
DBMS_ADVANCED_REWRITE.DROP_REWRITE_EQUIVALENCE(
'MACLEAN.STRMTC$RWEQ'
)
SQL>
CREATE
MATERIALIZED
VIEW
LOG
ON
"MACLEAN"
.
"STRC"
WITH
ROWID,
SEQUENCE
(
"T2"
,
"T3"
) INCLUDING NEW
VALUES
;
Materialized
view
log created.
SQL>
ALTER
MATERIALIZED
VIEW
LOG
FORCE
ON
"MACLEAN"
.
"STRC"
ADD
ROWID,
SEQUENCE
(
"T2"
,
"T3"
) INCLUDING NEW
VALUES
;
Materialized
view
log altered.
SQL>
CREATE
MATERIALIZED
VIEW
LOG
ON
"MACLEAN"
.
"STRD"
WITH
ROWID,
SEQUENCE
(
"T2"
,
"T3"
) INCLUDING NEW
VALUES
;
Materialized
view
log created.
SQL>
ALTER
MATERIALIZED
VIEW
LOG
FORCE
ON
"MACLEAN"
.
"STRD"
ADD
ROWID,
SEQUENCE
(
"T2"
,
"T3"
) INCLUDING NEW
VALUES
;
Materialized
view
log altered.
SQL>
CREATE
MATERIALIZED
VIEW
MACLEAN.STRMTC$SUB1 USING
INDEX
REFRESH FAST
WITH
ROWID
ON
COMMIT
ENABLE QUERY REWRITE
AS
SELECT
MACLEAN.STRC.T3 C1, MACLEAN.STRC.T2 C2,
COUNT
(*) M1
FROM
MACLEAN.STRC
GROUP
BY
MACLEAN.STRC.T3, MACLEAN.STRC.T2;
Materialized
view
created.
SQL>
CREATE
MATERIALIZED
VIEW
MACLEAN.STRMTC$SUB2 USING
INDEX
REFRESH FAST
WITH
ROWID
ON
COMMIT
ENABLE QUERY REWRITE
AS
SELECT
MACLEAN.STRD.T3 C1, MACLEAN.STRD.T2 C2,
COUNT
(*) M1
FROM
MACLEAN.STRD
GROUP
BY
MACLEAN.STRD.T3, MACLEAN.STRD.T2;
Materialized
view
created.
SQL>
CREATE
MATERIALIZED
VIEW
MACLEAN.STRMTC USING
INDEX
REFRESH
FORCE
WITH
ROWID
ENABLE QUERY REWRITE
AS
(
SELECT
"STRMTC$SUB1"
.
"C2"
"T2"
,
"STRMTC$SUB1"
.
"C1"
"T3"
,
"STRMTC$SUB1"
.
"M1"
"COUNT(*)"
FROM
"MACLEAN"
.
"STRMTC$SUB1"
"STRMTC$SUB1"
)
UNION
ALL
(
SELECT
"STRMTC$SUB2"
.
"C2"
"T2"
,
"STRMTC$SUB2"
.
"C1"
"T3"
,
"STRMTC$SUB2"
.
"M1"
"COUNT(*)"
FROM
"MACLEAN"
.
"STRMTC$SUB2"
"STRMTC$SUB2"
);
Materialized
view
created.
declare
v_state varchar2(2000);
begin
select
statement
into
v_state
from
dba_tune_mview
where
task_name =
'TASK_547'
and
action_id = 15;
v_state :=
'begin '
|| v_state ||
'; end;'
;
dbms_output.put_line(v_state);
execute
immediate v_state;
end
;
PL/SQL
procedure
successfully completed.
SQL>
set
linesize 200 pagesize 1400;
SQL>
select
t2,t3,
count
(*)
from
strc
group
by
t2,t3
2
union
all
3
select
t2,t3,
count
(*)
from
strd
group
by
t2,t3;
no
rows
selected
---------------------------------------------------------------------------------------------
| Id | Operation |
Name
|
Rows
| Bytes | Cost (%CPU)|
Time
|
---------------------------------------------------------------------------------------------
| 0 |
SELECT
STATEMENT | | 2 | 74 | 4 (50)| 00:00:01 |
| 1 |
UNION
-
ALL
| | | | | |
| 2 | MAT_VIEW REWRITE ACCESS
FULL
| STRMTC$SUB1 | 1 | 37 | 2 (0)| 00:00:01 |
| 3 | MAT_VIEW REWRITE ACCESS
FULL
| STRMTC$SUB2 | 1 | 37 | 2 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
/* 可以看到查询成功被rewrite为对2个物化视图的扫描 */
|
本文转自maclean_007 51CTO博客,原文链接:http://blog.51cto.com/maclean/1277704