物化檢視重新整理遞迴SQL獲取執行計劃報錯
發現trace中記錄的物化檢視的快速重新整理語句,拿到前臺sqlplus中無法獲取執行計劃。
在解決一個物化檢視重新整理問題的時候發現了這個現象,簡單搭建一個測試環境來說明這個問題:
SQL> CREATE TABLE T (OWNER VARCHAR2(30), NAME VARCHAR2(30), TYPE VARCHAR2(18));
表已建立。
SQL> CREATE MATERIALIZED VIEW LOG ON T WITH ROWID, SEQUENCE (OWNER, TYPE) INCLUDING NEW VALUES;
實體化檢視日誌已建立。
SQL> CREATE MATERIALIZED VIEW
MV_T
2 REFRESH FAST AS
3 SELECT OWNER, TYPE, COUNT(*) CN
4 FROM T
5 GROUP BY OWNER, TYPE;
實體化檢視已建立。
SQL> INSERT INTO T
2 SELECT OWNER, OBJECT_NAME, OBJECT_TYPE
3 FROM ALL_OBJECTS;
已建立40764行。
SQL> COMMIT;
提交完成。
SQL> ALTER SESSION SET EVENTS '10046 TRACE NAME CONTEXT FOREVER, LEVEL 12';
會話已更改。
SQL> EXEC DBMS_MVIEW.REFRESH('MV_T')
PL/SQL 過程已成功完成。
SQL> ALTER SESSION SET EVENTS '10046 TRACE NAME CONTEXT OFF';
會話已更改。
SQL> SELECT SPID
2 FROM V$PROCESS P, V$SESSION S
3 WHERE S.PADDR = P.ADDR
4 AND SYS_CONTEXT('USERENV', 'SID') = S.SID;
SPID
------------
4844
下面從得到的trace中找到物化檢視的快速重新整理語句:
.
.
.
=====================
PARSING IN CURSOR #2 len=40 dep=0 uid=57 ct=47 lid=57 tim=30719668925
hv=227083342 ad='284d57a0'
BEGIN DBMS_MVIEW.REFRESH('MV_T'); END;
END OF STMT
PARSE
#2:c=124801,e=625749,p=15,cr=517,cu=0,mis=1,r=0,dep=0,og=1,tim=30719668922
BINDS #2:
=====================
.
.
.
=====================
PARSING IN CURSOR #28 len=723 dep=1 uid=57 ct=189 lid=57 tim=30721489107
hv=3661396181 ad='23facb30'
/* MV_REFRESH (MRG) */ MERGE INTO "TEST"."MV_T"
"SNA$" USING (SELECT /*+ OPT_ESTIMATE(QUERY_BLOCK MAX=1000) */
"DLT$0"."OWNER" "GB0",
"DLT$0"."TYPE" "GB1", SUM(1) "D0" FROM
(SELECT CHARTOROWID("MAS$"."M_ROW$$") RID$ ,
"MAS$"."TYPE", "MAS$"."OWNER" FROM
"TEST"."MLOG$_T" "MAS$" WHERE
"MAS$".SNAPTIME$$ > :1 ) AS OF SNAPSHOT (:2) "DLT$0"
GROUP BY
"DLT$0"."OWNER","DLT$0"."TYPE")"AV$"
ON (SYS_OP_MAP_NONNULL("SNA$"."OWNER")=SYS_OP_MAP_NONNULL("AV$"."GB0")
AND
SYS_OP_MAP_NONNULL("SNA$"."TYPE")=SYS_OP_MAP_NONNULL("AV$"."GB1"))
WHEN MATCHED THEN UPDATE SET
"SNA$"."CN"="SNA$"."CN"+"AV$"."D0"
WHEN NOT MATCHED THEN INSERT ("SNA$"."OWNER",
"SNA$"."TYPE", "SNA$"."CN") VALUES (
"AV$"."GB0", "AV$"."GB1",
"AV$"."D0")
END OF STMT
PARSE #28:c=0,e=22051,p=1,cr=5,cu=4,mis=1,r=0,dep=1,og=1,tim=30721489105
=====================
.
.
.
=====================
PARSING IN CURSOR #23 len=210 dep=2 uid=0 ct=3 lid=0 tim=30721513236
hv=864012087 ad='2861192c'
select /*+ rule */ bucket_cnt, row_cnt, cache_cnt, null_cnt, timestamp#,
sample_size, minimum, maximum, distcnt, lowval, hival, density, col#, spare1,
spare2, avgcln from hist_head$ where obj#=:1 and intcol#=:2
END OF STMT
EXEC #23:c=0,e=133,p=0,cr=0,cu=0,mis=0,r=0,dep=2,og=3,tim=30721513235
FETCH #23:c=0,e=8,p=0,cr=2,cu=0,mis=0,r=0,dep=2,og=3,tim=30721513296
BINDS #28:
kkscoacd
Bind#0
acdty=12 mxl=07(07) mxlc=00 mal=00 scl=00 pre=00
acflg=10 fl2=0001 frm=00 csi=00 siz=8 ff=0
kxsbbbfp=05cd50c0 bln=07 avl=07 flg=09
value="5/24/2011 15:37:21"
Bind#1
acdty=23 mxl=32(24) mxlc=00 mal=00 scl=00 pre=00
acflg=10 fl2=0001 frm=00 csi=00 siz=32 ff=0
kxsbbbfp=05cd5054 bln=32 avl=24 flg=09
value=
Dump of memory from 0x05CD5054 to 0x05CD506C
5CD5050 D3AD1100 00000000 00000000 [............]
5CD5060 00000000 00000000 00000000 [............]
EXEC
#28:c=93600,e=123307,p=0,cr=43900,cu=35,mis=1,r=85,dep=1,og=1,tim=30721612532
STAT #28 id=1 cnt=2 pid=0 pos=1 bj=0 p='MERGE MV_T (cr=43740 pr=0 pw=0
time=98180 us)'
STAT #28 id=2 cnt=85 pid=1 pos=1 bj=0 p='VIEW (cr=43738 pr=0 pw=0 time=82388
us)'
STAT #28 id=3 cnt=85 pid=2 pos=1 bj=0 p='HASH JOIN RIGHT OUTER (cr=43738 pr=0
pw=0 time=82387 us)'
STAT #28 id=4 cnt=0 pid=3 pos=1 bj=52640 p='MAT_VIEW ACCESS FULL MV_T (cr=3
pr=0 pw=0 time=25 us)'
STAT #28 id=5 cnt=85 pid=3 pos=2 bj=0 p='VIEW (cr=43735 pr=0 pw=0 time=82073
us)'
STAT #28 id=6 cnt=85 pid=5 pos=1 bj=0 p='SORT GROUP BY (cr=43735 pr=0 pw=0
time=82073 us)'
STAT #28 id=7 cnt=40764 pid=6 pos=1 bj=52639 p='TABLE ACCESS FULL MLOG$_T
(cr=43735 pr=0 pw=0 time=40893 us)'
STAT #21 id=1 cnt=1 pid=0 pos=1 bj=0 p='UPDATE SNAP$ (cr=1 pr=0 pw=0 time=66
us)'
STAT #21 id=2 cnt=1 pid=1 pos=1 bj=217 p='INDEX UNIQUE SCAN I_SNAP1 (cr=1
pr=0 pw=0 time=7 us)'
=====================
雖然從trace中也可以獲取到執行計劃,但是格式看著很不舒服,於是打算直接將MERGE語句從EXPLAIN PLAN FOR進行分析,從而得到執行計劃:
SQL> EXPLAIN PLAN FOR
2 /* MV_REFRESH (MRG) */ MERGE INTO "TEST"."MV_T"
"SNA$"
3 USING
4 (
5 SELECT /*+ OPT_ESTIMATE(QUERY_BLOCK MAX=1000) */
6 "DLT$0"."OWNER" "GB0", "DLT$0"."TYPE"
"GB1", SUM(1) "D0"
7 FROM
8 (
9 SELECT CHARTOROWID("MAS$"."M_ROW$$") RID$ ,
"MAS$"."TYPE", "MAS$"."OWNER"
10 FROM "TEST"."MLOG$_T" "MAS$" WHERE
"MAS$".SNAPTIME$$ > :1
11 ) AS OF SNAPSHOT (:2) "DLT$0"
12 GROUP BY
"DLT$0"."OWNER","DLT$0"."TYPE"
13 )"AV$"
14 ON
15 (
16
SYS_OP_MAP_NONNULL("SNA$"."OWNER")=SYS_OP_MAP_NONNULL("AV$"."GB0")
17 AND
SYS_OP_MAP_NONNULL("SNA$"."TYPE")=SYS_OP_MAP_NONNULL("AV$"."GB1")
18 )
19 WHEN MATCHED THEN UPDATE
20 SET
"SNA$"."CN"="SNA$"."CN"+"AV$"."D0"
21 WHEN NOT MATCHED THEN
22 INSERT ("SNA$"."OWNER",
"SNA$"."TYPE", "SNA$"."CN")
23 VALUES ( "AV$"."GB0", "AV$"."GB1",
"AV$"."D0")
24 ;
) AS OF SNAPSHOT (:2) "DLT$0"
*
第 11 行出現錯誤:
ORA-08187: 此處不允許快照表示式
但是Oracle這裡出現了錯誤。
從錯誤資訊看,似乎這裡不允許指定SNAPSHOT表示式,而實際上Oracle的這個語句是內部語句,可以從SNAPSHOT語句的繫結變數也可以看到,這並不是一個常規的資料型別,Oracle在這裡並沒有解析這個值,而是直接顯示了記憶體DUMP的結果。
SQL> EXPLAIN PLAN FOR
2
/* MV_REFRESH (MRG) */ MERGE INTO "TEST"."MV_T"
"SNA$"
3
USING
4
(
5
SELECT /*+ OPT_ESTIMATE(QUERY_BLOCK MAX=1000) */
6
"DLT$0"."OWNER" "GB0",
"DLT$0"."TYPE" "GB1", SUM(1) "D0"
7
FROM
8
(
9
SELECT
CHARTOROWID("MAS$"."M_ROW$$") RID$ ,
"MAS$"."TYPE",
"MAS$"."OWNER"
10
FROM "TEST"."MLOG$_T" "MAS$" WHERE "MAS$".SNAPTIME$$ > :1
11
) "DLT$0"
12
GROUP BY
"DLT$0"."OWNER","DLT$0"."TYPE"
13
)"AV$"
14
ON
15
(
16
SYS_OP_MAP_NONNULL("SNA$"."OWNER")=SYS_OP_MAP_NONNULL("AV$"."GB0")
17
AND
SYS_OP_MAP_NONNULL("SNA$"."TYPE")=SYS_OP_MAP_NONNULL("AV$"."GB1")
18
)
19
WHEN MATCHED THEN UPDATE
20
SET
"SNA$"."CN"="SNA$"."CN"+"AV$"."D0"
21
WHEN NOT MATCHED THEN
22
INSERT ("SNA$"."OWNER",
"SNA$"."TYPE", "SNA$"."CN")
23
VALUES ( "AV$"."GB0",
"AV$"."GB1", "AV$"."D0")
24
;
已解釋。
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------
Plan hash value: 3001273056
-------------------------------------------------------------------------------------------
|Id| Operation |Name |Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0| MERGE STATEMENT
| | 85|
8075 | 167 (1)| 00:00:03 |
| 1| MERGE |MV_T |
| | | |
| 2| VIEW | | |
| | |
| 3| NESTED LOOPS OUTER | |
85| 7990 | 167
(1)| 00:00:03 |
| 4| VIEW | |
1| 41 | 166
(1)| 00:00:02 |
| 5| SORT GROUP BY | |
1| 37 | 166
(1)| 00:00:02 |
|*6| TABLE ACCESS FULL |MLOG$_T |
1| 37 | 165
(0)| 00:00:02 |
| 7| MAT_VIEW ACCESS BY INDEX
ROWID|MV_T | 85|
4505 | 1 (0)| 00:00:01 |
|*8| INDEX UNIQUE SCAN |I_SNAP$_MV_T| 1|
| 0 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
6 -
filter("MAS$"."SNAPTIME$$">:1)
8 -
access(SYS_OP_MAP_NONNULL("OWNER"(+))=SYS_OP_MAP_NONNULL("AV$"."GB0")
AND
SYS_OP_MAP_NONNULL("TYPE"(+))=SYS_OP_MAP_NONNULL("AV$"."GB1"))
Note
-----
- dynamic sampling used for this
statement
已選擇26行。
好在AS OF SNAPSHOT語法對於執行計劃沒有影響,去掉後就可以獲取這個語句的執行計劃了。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4227/viewspace-696195/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 獲取SQL執行計劃SQL
- 【檢視】使用V$SQL_PLAN檢視獲取曾經執行過的SQL語句執行計劃SQL
- 檢視sql執行計劃SQL
- 【sql調優之執行計劃】獲取執行計劃SQL
- Oracle 獲取SQL執行計劃方法OracleSQL
- 獲取SQL執行計劃的方式:SQL
- 執行計劃__獲取方法、檢視執行順序、統計資訊詳解
- 如何檢視SQL的執行計劃SQL
- 檢視SQL的執行計劃方法SQL
- 使用PL/SQL檢視執行計劃SQL
- Oracle 檢視SQL的執行計劃OracleSQL
- 檢視sql執行計劃--set autotraceSQL
- 執行計劃-1:獲取執行計劃
- 設定CURRENT_SCHEMA後獲取執行計劃報錯
- 檢視sql執行計劃方法彙總SQL
- MySQL 5.7 檢視理解SQL執行計劃MySql
- 【Explain Plan】檢視SQL的執行計劃AISQL
- 檢視執行計劃
- 建立job進行重新整理物化檢視,job執行失敗。
- 根據SQL_ID檢視執行計劃SQL
- 多種方法檢視Oracle SQL執行計劃OracleSQL
- 檢視sql執行計劃--set autotrace [final]SQL
- oracle10g 檢視SQL執行計劃OracleSQL
- 透過查詢檢視sql執行計劃SQL
- Oracle檢視正在執行的SQL以及執行計劃分析OracleSQL
- 物化檢視日誌表被DROP後建立物化檢視報錯
- 檢視執行計劃(一)
- 檢視執行計劃(二)
- 【物化檢視】根據物化檢視日誌快速重新整理物化檢視的過程
- MySQL 5.7獲取指定執行緒正在執行SQL的執行計劃資訊MySql執行緒
- 檢視Oracle SQL執行計劃方法比較、分析OracleSQL
- SQLPLUS檢視oracle sql執行計劃命令SQLOracle
- 檢視sql 執行計劃的歷史變更SQL
- 獲取執行計劃之Autotrace
- 獲取執行計劃的方法
- 獲取oracle sql語句詳細些執行計劃OracleSQL
- 【執行計劃】Oracle獲取執行計劃的幾種方法Oracle
- 物化檢視job無法執行