利用NO_MERGE解決資料字典檢視訪問低效 ZT
發表於: 2009.06.04 21:04
分類: ORACLE
出處: http://yangtingkun.itpub.net/post/468/485443
---------------------------------------------------------------
資料庫的資料字典檢視的訪問一般都比較迅速,因為Oracle已經做了專門的最佳化工作,但是有些時候,幾個資料字典進行關聯的時候,CBO就沒有那麼智慧了,有時候會給出一些效率很低的執行計劃。
比如在嘗試構造一個大表的時候,想要構造DBA_OBJECTS和另一張資料量不大的表DBA_SEQUENCES的笛卡兒積:
[oracle@localhost ~]$ sqlplus test/test
SQL*Plus: Release 9.2.0.4.0 - Production on 星期四 6月 4 16:39:58 2009
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
連線到:
Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.4.0 - Production
SQL> SET PAGES 100 LINES 128
SQL> COL PLAN_PLUS_EXP FORMAT A115
SQL> SET TIMING ON
SQL> SELECT COUNT(*) FROM DBA_SEQUENCES, DBA_OBJECTS;
COUNT(*)
----------
4585276
已用時間: 00: 31: 19.33
這個查詢居然執行了半個小時之久。
SQL> SELECT COUNT(*) FROM DBA_SEQUENCES;
COUNT(*)
----------
146
已用時間: 00: 00: 00.08
SQL> SELECT COUNT(*) FROM DBA_OBJECTS;
COUNT(*)
----------
31406
已用時間: 00: 00: 00.08
兩個檢視資料量都不算很大,笛卡兒積的結果無非也不過四百多萬,怎麼會執行這麼長時間呢:
SQL> EXPLAIN PLAN FOR
2 SELECT COUNT(*) FROM DBA_SEQUENCES, DBA_OBJECTS;
已解釋。
已用時間: 00: 00: 00.00
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
-----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | |
| 1 | SORT AGGREGATE | | | | |
| 2 | NESTED LOOPS | | | | |
| 3 | NESTED LOOPS | | | | |
| 4 | NESTED LOOPS | | | | |
| 5 | VIEW | DBA_OBJECTS | | | |
| 6 | UNION-ALL | | | | |
|* 7 | FILTER | | | | |
| 8 | TABLE ACCESS BY INDEX ROWID| OBJ$ | | | |
| 9 | NESTED LOOPS | | | | |
| 10 | TABLE ACCESS FULL | USER$ | | | |
|* 11 | INDEX RANGE SCAN | I_OBJ2 | | | |
|* 12 | TABLE ACCESS BY INDEX ROWID| IND$ | | | |
|* 13 | INDEX UNIQUE SCAN | I_IND1 | | | |
| 14 | NESTED LOOPS | | | | |
| 15 | TABLE ACCESS FULL | USER$ | | | |
|* 16 | INDEX RANGE SCAN | I_LINK1 | | | |
| 17 | TABLE ACCESS FULL | USER$ | | | |
| 18 | TABLE ACCESS BY INDEX ROWID | OBJ$ | | | |
|* 19 | INDEX RANGE SCAN | I_OBJ2 | | | |
|* 20 | INDEX UNIQUE SCAN | I_SEQ1 | | | |
-----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
7 - filter("SYS_ALIAS_1"."TYPE#"<>1 AND "SYS_ALIAS_1"."TYPE#"<>10 OR
"SYS_ALIAS_1"."TYPE#"=1 AND (SELECT 1 FROM "SYS"."IND$" "I" WHERE "I"."OBJ#"=:B1
AND ("I"."TYPE#"=1 OR "I"."TYPE#"=2 OR "I"."TYPE#"=3 OR "I"."TYPE#"=4 OR
"I"."TYPE#"=6 OR "I"."TYPE#"=7 OR "I"."TYPE#"=9))=1)
11 - access("SYS_ALIAS_1"."OWNER#"="U"."USER#" AND "SYS_ALIAS_1"."LINKNAME" IS
NULL)
filter("SYS_ALIAS_1"."LINKNAME" IS NULL AND
"SYS_ALIAS_1"."NAME"<>'_default_auditing_options_' AND
"SYS_ALIAS_1"."NAME"<>'_NEXT_OBJECT')
12 - filter("I"."TYPE#"=1 OR "I"."TYPE#"=2 OR "I"."TYPE#"=3 OR "I"."TYPE#"=4 OR
"I"."TYPE#"=6 OR "I"."TYPE#"=7 OR "I"."TYPE#"=9)
13 - access("I"."OBJ#"=:B1)
16 - access("L"."OWNER#"="U"."USER#")
19 - access("U"."USER#"="O"."OWNER#")
20 - access("O"."OBJ#"="S"."OBJ#")
Note: rule based optimization
已選擇47行。
已用時間: 00: 00: 00.33
檢查執行計劃發現,由於兩個檢視的一些資料來自相同的內部CLUSTER表,於是CBO“聰明地”修改了執行計劃,將兩個檢視的查詢拆散,重新構造了執行計劃。
而事實證明這個執行計劃是十分糟糕的。由於單個檢視都是經過Oracle最佳化過的,因此單獨訪問任何一個檢視都沒有效能問題,於是利用NO_MERGE提示,避免Oracle將檢視的查詢拆散:
SQL> SET AUTOT ON
SQL> SELECT /*+ NO_MERGE(A) NO_MERGE(B) */ COUNT(*)
2 FROM DBA_SEQUENCES A, DBA_OBJECTS B;
COUNT(*)
----------
4585276
已用時間: 00: 00: 00.60
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=204251 Card=1)
1 0 SORT (AGGREGATE)
2 1 MERGE JOIN (CARTESIAN) (Cost=204251 Card=66724392)
3 2 VIEW OF 'DBA_OBJECTS' (Cost=26 Card=8169)
4 3 UNION-ALL
5 4 FILTER
6 5 NESTED LOOPS (Cost=12 Card=1 Bytes=135)
7 6 TABLE ACCESS (FULL) OF 'OBJ$' (Cost=11 Card=1 Bytes=122)
8 6 TABLE ACCESS (CLUSTER) OF 'USER$' (Cost=1 Card=1 Bytes=13)
9 8 INDEX (UNIQUE SCAN) OF 'I_USER#' (NON-UNIQUE)
10 5 TABLE ACCESS (BY INDEX ROWID) OF 'IND$' (Cost=2 Card=1 Bytes=26)
11 10 INDEX (UNIQUE SCAN) OF 'I_IND1' (UNIQUE) (Cost=1 Card=8168)
12 4 HASH JOIN (Cost=14 Card=8168 Bytes=212368)
13 12 TABLE ACCESS (FULL) OF 'LINK$' (Cost=2 Card=82 Bytes=1066)
14 12 TABLE ACCESS (FULL) OF 'USER$' (Cost=11 Card=8168 Bytes=106184)
15 2 BUFFER (SORT) (Cost=204251 Card=8168)
16 15 VIEW OF 'DBA_SEQUENCES' (Cost=25 Card=8168)
17 16 NESTED LOOPS (Cost=25 Card=8168 Bytes=424736)
18 17 HASH JOIN (Cost=25 Card=8168 Bytes=318552)
19 18 TABLE ACCESS (FULL) OF 'USER$' (Cost=11 Card=8168 Bytes=106184)
20 18 TABLE ACCESS (FULL) OF 'OBJ$' (Cost=11 Card=8168 Bytes=212368)
21 17 INDEX (UNIQUE SCAN) OF 'I_SEQ1' (UNIQUE)
Statistics
----------------------------------------------------------
14 recursive calls
0 db block gets
68435 consistent gets
0 physical reads
0 redo size
379 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
1 rows processed
可以看到,二者的效率可謂天壤之別,一個需要30多分鐘,另一個執行不到1秒。從執行計劃上看,利用NO_MERGE提示後,Oracle沒有將兩個檢視的執行計劃打散,而是直接對兩個檢視訪問的結果進行笛卡兒積,而這正是我們希望的結果。
這個方法並不是特例,很多訪問資料字典檢視的效能問題,都可以透過這個方法來解決。
也有有人會置疑,從執行計劃上看,明顯第一個SQL是RBO,而第二個SQL由於加上了HINT,最佳化器採用CBO,是否由於CBO優於RBO導致效率的提升。
事實上,採用CBO,確實可以提高訪問效率,至少得到的執行計劃沒有那麼離譜,但是與NO_MERGE提示的效果相比,還是要遜色不少:
SQL> SELECT /*+ ALL_ROWS */ COUNT(*) FROM DBA_SEQUENCES, DBA_OBJECTS;
COUNT(*)
----------
4585276
已用時間: 00: 00: 02.78
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=HINT: ALL_ROWS (Cost=50919 Card=1 Bytes=52)
1 0 SORT (AGGREGATE)
2 1 HASH JOIN (Cost=50919 Card=66724392 Bytes=3469668384)
3 2 TABLE ACCESS (FULL) OF 'USER$' (Cost=11 Card=8168 Bytes=106184)
4 2 HASH JOIN (Cost=40483 Card=66724392 Bytes=2602251288)
5 4 TABLE ACCESS (FULL) OF 'OBJ$' (Cost=11 Card=8168 Bytes=212368)
6 4 MERGE JOIN (CARTESIAN) (Cost=32702 Card=66724392 Bytes=867417096)
7 6 VIEW OF 'DBA_OBJECTS' (Cost=26 Card=8169)
8 7 UNION-ALL
9 8 FILTER
10 9 NESTED LOOPS (Cost=12 Card=1 Bytes=135)
11 10 TABLE ACCESS (FULL) OF 'OBJ$' (Cost=11 Card=1 Bytes=122)
12 10 TABLE ACCESS (CLUSTER) OF 'USER$' (Cost=1 Card=1 Bytes=13)
13 12 INDEX (UNIQUE SCAN) OF 'I_USER#' (NON-UNIQUE)
14 9 TABLE ACCESS (BY INDEX ROWID) OF 'IND$' (Cost=2 Card=1 Bytes=26)
15 14 INDEX (UNIQUE SCAN) OF 'I_IND1' (UNIQUE) (Cost=1 Card=8168)
16 8 HASH JOIN (Cost=14 Card=8168 Bytes=212368)
17 16 TABLE ACCESS (FULL) OF 'LINK$' (Cost=2 Card=82 Bytes=1066)
18 16 TABLE ACCESS (FULL) OF 'USER$' (Cost=11 Card=8168 Bytes=106184)
19 6 BUFFER (SORT) (Cost=32702 Card=8168 Bytes=106184)
20 19 INDEX (FAST FULL SCAN) OF 'I_SEQ1' (UNIQUE) (Cost=4 Card=8168 Bytes=106184)
Statistics
----------------------------------------------------------
14 recursive calls
0 db block gets
68436 consistent gets
1 physical reads
0 redo size
379 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
1 rows processed
可以看到,使用CBO比RBO情況要好很多,但是執行時間仍然是使用NO_MERGE的4倍多。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/82387/viewspace-1023637/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- (zt)利用NO_MERGE解決資料字典檢視訪問低效
- 利用NO_MERGE解決資料字典檢視訪問低效
- “no_merge”hints優化檢視訪問低效問題優化
- 檢視資料字典
- Oracle 資料字典和資料字典檢視Oracle
- SQLServer訪問Oracle(通過同義詞-檢視-資料字典)出現的問題SQLServerOracle
- 深入瞭解Oracle資料字典(zt)Oracle
- oracle常用資料字典.檢視Oracle
- 【檢視】oracle 資料字典檢視之 DICT / DICTIONARYOracle
- 2.12 資料庫資料字典檢視資料庫
- Oracle相關資料字典檢視Oracle
- 使用資料字典檢視管理物件物件
- 【轉載】Oracle資料字典檢視Oracle
- oracle資料字典表與檢視Oracle
- 用檢視解決資料庫鏈路問題資料庫
- Oracle 資料字典大全 ZTOracle
- 【檢視】oracle 資料字典檢視之 “小”檢視 CAT, TAB, SEQ, SYN ...Oracle
- Oracle 資料庫字典 檢視 基表Oracle資料庫
- 系統表和資料字典檢視
- DBA常用的資料字典檢視(一)
- 常用的資料字典檢視和包
- 2.8.3 資料庫服務的資料字典檢視資料庫
- ZT 物化檢視詳解
- 控制普通使用者訪問資料字典
- 檢視低效的SQL語句SQL
- [zt]prebuilt 物化檢視遷移資料庫UI資料庫
- PHP利用Redis鎖解決併發訪問PHPRedis
- Oracle OCP(27):使用資料字典檢視管理物件Oracle物件
- Oracle 常用資料字典表、檢視的總結Oracle
- 資料字典和動態效能檢視基礎
- 【VIEW】Oracle資料字典檢視之DICT_COLUMNSViewOracle
- Oracle 常用資料字典檢視、表的總結Oracle
- 動態sql和利用動態sql解決資料字典的讀取SQL
- [Q]怎麼檢視資料庫引數 zt資料庫
- [20130125]利用v$active_session_history檢視解決資料庫問題.txtSession資料庫
- 谷歌利用資料解決女性員工流失問題谷歌
- 解決資料庫高併發訪問瓶頸問題資料庫
- Oracle資料庫訪問限制繞過漏洞 解決Oracle資料庫