在繫結變數下使用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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 如何在對in操作使用變數繫結(轉)變數
- Vue select 繫結動態變數Vue變數
- MySQL高階特性——繫結變數MySql變數
- [20180930]in list與繫結變數.txt變數
- [20180912]PLSLQ與繫結變數.txt變數
- [20210120]in list與繫結變數個數.txt變數
- [20180930]in list與繫結變數個數.txt變數
- V$sql查詢未使用繫結變數的語句SQL變數
- 【ORACLE】Oracle繫結變數知識梳理Oracle變數
- 繫結變數窺視測試案例變數
- [20220414]toad與繫結變數peek.txt變數
- [20200326]繫結變數抓取與NULL值.txt變數Null
- 如何用FGA得到繫結變數的值變數
- Oracle中如何查詢未使用繫結變數的SQL語句?Oracle變數SQL
- [20231210]執行計劃與繫結變數.txt變數
- [20190506]檢視巢狀與繫結變數.txt巢狀變數
- [20221103]繫結變數的分配長度11.txt變數
- [20221030]繫結變數的分配長度10.txt變數
- [20191213]共享池繫結變數的值在哪裡.txt變數
- 在 Linux 中使用變數Linux變數
- 透過v$sql_bind_capture 檢視繫結變數。SQLAPT變數
- 後期靜態繫結在PHP中的使用PHP
- 在原生CSS中使用變數CSS變數
- Oracle面對“資料傾斜列使用繫結變數”場景的解決方案Oracle變數
- [20211227]抽取跟蹤檔案中的繫結變數值.txt變數
- [20191216]共享池繫結變數的值在哪裡2.txt變數
- [20210112]完善查詢繫結變數指令碼bind_cap.txt變數指令碼
- OpenMP 環境變數使用總結變數
- 越來越發現自己不懂的還是不少--繫結變數變數
- Oracle資料傾斜導致的問題-無繫結變數Oracle變數
- Oracle資料傾斜導致的問題-有繫結變數Oracle變數
- zepto繫結事件改變冒泡事件流事件
- Grails中如何繫結引數AI
- 【CURSOR】Oracle繫結變數、執行計劃對遊標的影響Oracle變數
- oracle 11g 新特性之動態繫結變數窺視(一)Oracle變數
- oracle 11g 新特性之動態繫結變數窺視(二)Oracle變數
- WPF使用MVVM(二)-命令繫結MVVM
- IsWorld使用-公眾號繫結