在繫結變數下使用outline
前段時間寫了一篇文章,簡單介紹如何使用outline,原文地址:
http://space6212.itpub.net/post/12157/145831
原來的文章主要針對非繫結變數的情況的,但在實際中我們會使用到繫結變數,今天我們就接著討論下使用繫結變數時如何使用outline
用outline穩定執行計劃
--建立測試資料
SQL> create table t_outline as select * from all_objects where owner='SUK';
Table created
SQL> create index idx_t_outline on t_outline(owner);
Index created
> select owner,count(1) from t_outline group by owner;
OWNER COUNT(1)
------------------------------ ----------
SUK 145920
> var o varchar2(20)> exec :o:='SUK'
PL/SQL 過程已成功完成。
--RBO下用索引掃描,根據資料分佈可知,索引掃描效率是很低的> select * from t_outline where owner=:o;
已選擇145920行。
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'T_OUTLINE'
2 1 INDEX (RANGE SCAN) OF 'IDX_T_OUTLINE' (NON-UNIQUE)
--分析表,查詢走全表掃描> analyze table t_outline compute statistics;
表已分析。
> select * from t_outline where owner=:o;
已選擇145920行。
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=174 Card=145920 Byte
s=11089920)
1 0 TABLE ACCESS (FULL) OF 'T_OUTLINE' (Cost=174 Card=145920 B
ytes=11089920)
--可以看到,從全表掃描效率明顯比索引掃描高,故可以用outline穩定該查詢的執行計劃,使之在RBO下也可以走全表掃描
--以CBO下的執行計劃作為outline的執行計劃 > CREATE OUTLINE test_t_outline FOR CATEGORY test_outline ON select * from t_outline where owner=:o;
大綱已建立。
--刪除統計資料,使查詢走RBO> analyze table t_outline delete statistics;
表已分析。
> select * from t_outline where owner=:o;
已選擇145920行。
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'T_OUTLINE'
2 1 INDEX (RANGE SCAN) OF 'IDX_T_OUTLINE' (NON-UNIQUE)
--沒有用outline的情況下走的是索引掃描
> alter session set use_stored_outlines =test_outline;
--啟用outline
會話已更改。
> select * from t_outline where owner=:o;
已選擇145920行。
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=174 Card=1460 Bytes=
186880)
1 0 TABLE ACCESS (FULL) OF 'T_OUTLINE' (Cost=174 Card=1460 Byt
es=186880)
--可以看到,啟用outline可以讓查詢在RBO下也走全表掃描,提高了效率
--稍微修改SQL,看SQL不完全一致的情況下outline是否起作用> SELECT * FROM T_OUTLINE where owner=:o;
已選擇145920行。
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=174 Card=1460 Bytes=
186880)
1 0 TABLE ACCESS (FULL) OF 'T_OUTLINE' (Cost=174 Card=1460 Byt
es=186880)
--從上面的執行計劃可知,SQL不完全一致的情況下,outline也起作用。測試可知,即使原來的sql分成多行仍然可以用outline。
--實際上,outline在分析某條sql是否可用儲存大綱的時候會把這條sql的空格全部去掉,並且會把sql全部轉換成大寫再進行比較,所以,只要sql的去掉所有空格後的字元一致就可以用到儲存在庫中與之對應的outline。但像這種語句是不能用到outline的
SQL> SELECT * FROM T_OUTLINE T where owner=:o;
--上面的SQL因為多了一個T,所以不能用到outline。
--我們使用outline時需要注意使用繫結變數,否則outline能應用的範圍就很小了(當然針對特殊的查詢需要特殊對待的除外),但是,如果繫結變數的變數名不一樣,oracle是不會用outline的。如
> var a varchar2(20)> exec :a:='SUK'
PL/SQL 過程已成功完成。
> SELECT * FROM T_OUTLINE where owner=:a;
已選擇145920行。
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'T_OUTLINE'
2 1 INDEX (RANGE SCAN) OF 'IDX_T_OUTLINE' (NON-UNIQUE)
--從上面的測試可知,我們在編寫程式時,在不同的地方使用相同的sql應儘量使用相同的變數名
--如果沒有使用繫結變數,且cursor_sharing不為force,我們很容易就可以推斷出這種情況下能用到outline的機率很小,只有去空格並轉成大寫後的SQL完全一樣時才會用到outline。但我們知道,如果cursor_sharing=force,oracle會強制把具體值轉換成變數,使得sql以繫結變數的方式執行,那麼,是不是說cursor_sharing=force就可以使不繫結變數、且條件值不一樣的sql用outline呢?
透過試驗可以得知
當cursor_sharing=force時,
普通查詢:select * from t_outline where owner='SUK' 會轉化為:select * from t_outline where owner=:"SYS_B_0"
但在建立outline時:
CREATE OUTLINE test_t_outline FOR CATEGORY test_outline ON select * from t_outline where owner='SUK';
在OL$中儲存的仍然是:select * from t_outline where owner='SUK' ,
而不是:select * from t_outline where owner=:"SYS_B_0"
--所以如果資料庫沒有使用繫結變數,無論cursor_sharing為什麼值,如果想要用到outline,去空格並轉成大寫後的SQL必須一樣(包括條件值)。
結論:
無論cursor_sharing設定成什麼、是否使用繫結變數,如果要用到outline,則唯一的條件是:執行查詢的SQL必須與CREATE OUTLINE後接的SQL在分別去空格並轉換成大寫後一樣。也就是說,即使繫結使用變數,包括繫結的變數名也必須一樣。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/231499/viewspace-63727/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- PLSQL使用繫結變數SQL變數
- 【優化】使用繫結變數 OR 不使用繫結變數,這不是問題!優化變數
- 【最佳化】使用繫結變數 OR 不使用繫結變數,這不是問題!變數
- 在oracle的plsql中為cursor使用繫結變數OracleSQL變數
- 繫結變數變數
- SQL Developer中使用繫結變數SQLDeveloper變數
- 繫結變數的使用範圍變數
- 關於繫結變數的使用變數
- 使用繫結變數的一點總結!變數
- 繫結變數之繫結變數窺探(Bind Peeking)變數
- Oracle 繫結變數Oracle變數
- 【SQL】在SQLPLUS中使用繫結變數的寫法SQL變數
- 【sql調優】使用繫結變數(二)SQL變數
- 【sql調優】使用繫結變數(一)SQL變數
- 繫結變數優缺點、使用、繫結變數窺探、 Oracle自適應共享遊標變數Oracle
- 如何在對in操作使用變數繫結(轉)變數
- PLSQL中使用繫結變數的語法SQL變數
- java程式裡怎麼使用繫結變數Java變數
- SQL使用繫結變數,測試例項。SQL變數
- 檢視繫結變數變數
- 繫結變數窺測變數
- Oracle之繫結變數Oracle變數
- 關於繫結變數變數
- ORACLE 繫結變數用法總結Oracle變數
- OLTP系統中儘量使用繫結變數變數
- oracle 查詢未使用繫結變數的sqlOracle變數SQL
- 繫結變數窺測的演變變數
- Oracle 變數繫結與變數窺視合集Oracle變數
- 繫結變數的測試變數
- Oracle 繫結變數窺探Oracle變數
- oracle 繫結變數(bind variable)Oracle變數
- 如何獲取繫結變數變數
- Oracle 繫結變數 詳解Oracle變數
- 在php中使用繫結變數的方法(Oracle SQL共享的機制)(轉)PHP變數OracleSQL
- 繫結變數在靜態sql和動態sql中變數SQL
- 關於繫結變數的SQL繫結什麼值變數SQL
- SQL*Plus中使用DATE型別的繫結變數SQL型別變數
- 什麼時候使用繫結變數效能反而更差變數