繫結變數和cursor_sharing
如果SHARED_POOL_SIZE設定得足夠大,又可以排除Bug的因素,那麼大多數的ORA-04031錯誤都是由共享池中的大量SQL程式碼等導致過多記憶體碎片引起的。
可能的主要原因有:
·SQL沒有足夠的共享;
·大量不必要的解析呼叫;
·沒有使用繫結變數。
實際上說,應用的編寫和調整始終是最重要的內容,Shared Pool的調整根本上要從應用入手。根本上,使用繫結變數可以充分降低Shared Pool和Library Cache的Latch競爭,從而提高效能。
反覆的SQL硬解析不僅會消耗大量的CPU資源,也會佔用更多的記憶體,嚴重影響資料庫效能,而使用繫結變數則可以使SQL充分共享,實現SQL的軟解析,提高系統效能。以下是Oracle 10g中一個關於繫結變數和非繫結變數的測試對比,由此可以略窺繫結效能影響之一斑。
首先建立測試表並記錄解析統計資料:
sys@NEI> select * from v$version where rownum<2;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
tq@NEI> create table dbtan (id number);
表已建立。
tq@NEI> select name,value from v$mystat a,v$statname b where a.statistic#=b.statistic# and name like 'parse%';
NAME VALUE
------------------------------ ---------
parse time cpu 11
parse time elapsed 140
parse count (total) 189
parse count (hard) 30
parse count (failures) 2
進行迴圈插入資料,以下程式碼並未使用繫結變數:
tq@NEI> begin
2 for i in 1..10 loop
3 execute immediate 'insert into dbtan values('||i||')';
4 end loop;
5 commit;
6 end;
7 /
PL/SQL 過程已成功完成。
完成之後檢查統計資訊,注意硬解析數增加了10次,也就是說每次INSERT操作都需要進行一次獨立的解析:
tq@NEI> select name,value from v$mystat a,v$statname b where a.statistic#=b.statistic# and name like 'parse%';
NAME VALUE
------------------------------ ---------
parse time cpu 13
parse time elapsed 159
parse count (total) 205
parse count (hard) 40
parse count (failures) 2
查詢v$sqlarea檢視,可以找到這些不能共享的SQL,注意每條SQL都只執行了一次,這些SQL不僅解析要消耗密集的SQL資源,也要佔用共享記憶體儲存這些不同的SQL程式碼:
tq@NEI> col sql_text for a40
tq@NEI> select sql_text,version_count,parse_calls,executions
2 from v$sqlarea
3 where sql_text like 'insert into dbtan%';
SQL_TEXT VERSION_COUNT PARSE_CALLS EXECUTIONS
---------------------------------------- ------------- ----------- ----------
insert into dbtan values(10) 1 1 1
insert into dbtan values(3) 1 1 1
insert into dbtan values(6) 1 1 1
insert into dbtan values(7) 1 1 1
insert into dbtan values(2) 1 1 1
insert into dbtan values(1) 1 1 1
insert into dbtan values(8) 1 1 1
insert into dbtan values(5) 1 1 1
insert into dbtan values(9) 1 1 1
insert into dbtan values(4) 1 1 1
已選擇10行。
重建測試表,進行第二次測試:
tq@NEI> drop table dbtan purge;
表已刪除。
tq@NEI> create table dbtan (id number);
表已建立。
tq@NEI> select name,value from v$mystat a,v$statname b where a.statistic#=b.statistic# and name like 'parse%';
NAME VALUE
------------------------------ ---------
parse time cpu 34
parse time elapsed 294
parse count (total) 748
parse count (hard) 141
parse count (failures) 3
這一次使用繫結變數,同樣10次資料插入:
tq@NEI> begin
2 for i in 1..10 loop
3 execute immediate 'insert into dbtan values(:v1)' using i;
4 end loop;
5 commit;
6 end;
7 /
PL/SQL 過程已成功完成。
現在看一下SQL解析的統計資料庫,硬解析由原來的141增加到143
tq@NEI> select name,value from v$mystat a,v$statname b where a.statistic#=b.statistic# and name like 'parse%';
NAME VALUE
------------------------------ ---------
parse time cpu 34
parse time elapsed 295
parse count (total) 755
parse count (hard) 143
parse count (failures) 3
對於該SQL,共享池中只存在一份,解析一次,執行10次,這就是繫結變數的優勢所在:
tq@NEI> select sql_text,version_count,parse_calls,executions
2 from v$sqlarea
3 where sql_text like 'insert into dbtan%';
SQL_TEXT VERSION_COUNT PARSE_CALLS EXECUTIONS
---------------------------------------- ------------- ----------- ----------
insert into dbtan values(:v1) 1 1 10
在應用程式開發的過程中,都應該優先考慮使用繫結變數(在JAVA應用中可以使用PreparedStatement進行變數繫結),但是如果應用沒有很好地使用繫結變數,那麼Oracle從8.1.6開始提供了一個新的初始化引數用以在Server端進行強制變數繫結,這個引數就是cursor_sharing。最初這個引數有兩個可選設定:exact和force。
預設值是exact,表示精確匹配;force表示在Server端執行強制繫結。在8i的版本里使用這個引數對某些應用可以帶來極大的效能提高,但是同時也存在一些副作用,比如優化器無法生成精確的執行計劃,SQL執行計劃發生改變等(所以如果啟用cursor_sharing引數時,一定確認使用者的應用在此模式下經過充分的測試)。
從Oracle 9i開始,Oracle引入了繫結變數Peeking的機制,SQL在第一次執行時,首先在Session的PGA中使用具體值生成精確的執行計劃,以期可以提高執行計劃的準確性,然而Peeking的方式只有在第一次硬解析時生效,所以仍然可能存在問題,導致後續的SQL錯誤的執行;同時,在Oracle 9i中,cursor_sharing引數有了第3個選項:similar。該引數指定Oracle在存在柱狀圖資訊時,對於不同的變數值,重新解析,從而可以利用柱狀圖更加精確地制定SQL執行計劃。也即當存在柱狀圖資訊時,similar的表現和exact相同;當柱狀圖資訊不存在時,similar的表現和force相同。
但是需要注意的是,在某些版本中(如:Oracle 9.2.0.5),設定cursor_sharing為similar可能導致SQL的version_count過高的Bug,該選項在不同版本中都可能存在問題,是需要斟酌使用的一個引數,設定該引數不過是一個臨時的解決辦法,根本的效能提升仍然需要通過優化SQL來解決。
除了Bug之外,在正常情況下,由於Similar的判斷機制,可能也會導致SQL無法共享。在收集了柱狀圖(Hisogram)資訊之後,如果SQL未使用繫結變數,當SQL使用具備柱狀圖資訊的Column時,資料庫會認為SQL傳遞過來的每個常量都是不可靠的,需要為每個SQL生成一個Cursor,這種情況被稱為UNSAFE BINDS。大量的version_count可能會導致資料庫產生大量的cursor:pin S wait on X等待。解決這類問題,可以設定cursor_sharing為FORCE或者刪除相應欄位上的柱狀圖資訊。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8183550/viewspace-659597/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- zt_繫結變數和cursor_sharing變數
- 繫結變數變數
- 繫結變數和BIND PEEKING變數
- 繫結變數之繫結變數窺探(Bind Peeking)變數
- Oracle 繫結變數Oracle變數
- 檢視繫結變數變數
- 繫結變數窺測變數
- PLSQL使用繫結變數SQL變數
- Oracle之繫結變數Oracle變數
- 關於繫結變數變數
- 【優化】使用繫結變數 OR 不使用繫結變數,這不是問題!優化變數
- ORACLE 繫結變數用法總結Oracle變數
- 【最佳化】使用繫結變數 OR 不使用繫結變數,這不是問題!變數
- 繫結變數窺測的演變變數
- Oracle 變數繫結與變數窺視合集Oracle變數
- 繫結變數的測試變數
- Oracle 繫結變數窺探Oracle變數
- oracle 繫結變數(bind variable)Oracle變數
- 如何獲取繫結變數變數
- Oracle 繫結變數 詳解Oracle變數
- cursor_sharing=force強制繫結變數不會把變數值預設當成varchar2型別的理解變數型別
- 關於繫結變數的SQL繫結什麼值變數SQL
- MySQL高階特性——繫結變數MySql變數
- SQL Developer中使用繫結變數SQLDeveloper變數
- 繫結變數之基本概念變數
- ORACLE 獲取繫結變數值Oracle變數
- 繫結變數及其優缺點變數
- 繫結變數的一個例子變數
- 如何獲取繫結變數值變數
- 繫結變數的使用範圍變數
- oracle繫結變數的測試Oracle變數
- 查詢繫結變數的值變數
- 關於繫結變數的使用變數
- oracle繫結變數窺視(zt)Oracle變數
- 使用繫結變數的一點總結!變數
- 繫結變數優缺點、使用、繫結變數窺探、 Oracle自適應共享遊標變數Oracle
- 【原創】Oracle 變數繫結與變數窺視合集Oracle變數
- 繫結變數在靜態sql和動態sql中變數SQL