引數 session_cached_cursors 與 open_cursors詳解
一、OPEN_CURSORS
就是一個session同時開啟的cursor的數量上限。
確定open_cursors
select max(count(*)) max_cacheable_cursors
from (select p.kglobt18 schema# -- parsing schema number
from sys.x$kglcursor p
where p.kglobt12 > 2 -- enough parse_calls
union all
select s.kglntsnm schema# -- authorized schema number
from sys.x$kglcursor c, sys.x$kglsn s
where c.kglobt12 > 2
and s.kglhdadr = c.kglhdadr)
group by schema#
二、SESSION_CACHED_CURSORS
就是說一個session可以快取多少個cursor,讓後續相同的SQL語句不再開啟遊標,從而避免軟解析的過程來提高效能。(繫結變數是解決硬解析的問題),軟解析同硬解析一樣,比較消耗資源。所以這個引數非常重要。
oracle有一個概念,那就是session cursor cache,中文描述就是有一塊記憶體區域,用來儲存關閉了的cursor。當一個cursor關閉之後,oracle會檢查這個cursor的request次數是否超過3次,如果超過了三次,就會放入session cursor cache,這樣在下次parse的時候,就可以從session cursor cache中找到這個statement, session cursor cache的管理也是使用LRU。
session_cached_cursors這個引數是控制session cursor cache的大小的。session_cached_cursors定義了session cursor cache中儲存的cursor的個數。這個值越大,則會消耗的記憶體越多。
另外檢查這個引數是否設定的合理,可以從兩個statistic來檢查。
SQL> select name,value from v$sysstat where name like '%cursor%';
NAME VALUE
---------------------------------------------------------------- ----------
opened cursors cumulative 21577316
opened cursors current 2399
session cursor cache hits 9992832
session cursor cache count 8254
cursor authentications 434123
SQL> select name,value from v$sysstat where name like '%parse%';
NAME VALUE
---------------------------------------------------------------- ----------
parse time cpu 1400526
parse time elapsed 13979044
parse count (total) 20982181
parse count (hard) 1396983
parse count (failures) 10958
session cursor cache hits 和parse count(total) 就是總的parse次數中,在session cursor cache中找到的次數。所佔比例越高,效能越好。如果比例比較低,並且有剩餘記憶體的話,可以考慮加大該引數。
Oracle 9i及以前,該引數預設是0,10G上預設是20。
設定pga端的cache list的長度,當session_cached_cursors設定為0時,pga的cache list長度為0,這時候當sga中的cursor關閉的時候它相關的library cache handle的lock位被清0,從v$open_cursor裡看不到這個被關閉的cursor,它服從於shared pool的lru機制,當shared pool需要新的buffer空間時,它將會被flush出shared pool。當session_cached_cursors設定為非0值時,pga的cache list長度為session_cached_cursors值的大小,同時pga cache list將會保留一份複製,這時候即使sga中的cursor關閉的時候它相關的library cache handle始終被加了null mode lock,當shared pool空間緊張時library cache handle始終將會被保留在shared pool中,而新的應用訪問這個cursor的時候會直接去自己的pga cache list裡面搜尋。
cursor_space_for_time:
當設定了session_cached_cursors為非0值後,如果cursor_space_for_time值被設為false,那麼當shared pool空間緊張時,雖然library cache handle不會被flush出去,但是它指向的library cached object(lco,其中包含了handle和children handle的地址,許可權,型別,狀態,指向kgl block的指標,其中kgl block包含了真正的程式碼段和執行計劃等內容)將會被flush出去而不管它相關的cursor有沒關閉,如果需要lco的時候將要reloads。如果cursor_space_for_time值被設為true,那麼當cursor在開啟狀態下,handle指向的lco將不會被flush出shared pool,這樣就可以降低reloads出現的頻率。不過對於sql共享做的不好的資料庫,設定cursor_space_for_time將會帶來一些問題,share pool可能會出現04031的錯誤。
gets:
當試圖parse一句sql時,oracle要先獲得一個handle,在handle上載入一個lock,gets表示handle request times。
pin:
當獲得handle後,定位到lco,然後pin住lco使它在被執行的時候不被flush出去。
二、引用ASKTOM相關內容如下
Hi Tom
Can you explain briefly the difference between soft and hard parse?
你能不能給我詳細介紹一下軟解析與硬解析的區別啊?
and we said...
Here is a long winded answer, it is extracted in part from a new book oming out soon "beginning Oracle programming" that I collaborated on:
這是一個很長的解釋,是從我與幾個同事一起合著的新書<>中提取出來的.
解析
This is the first step in the processing of any statement in Oracle. Parsing is the act of breaking the submitted statement down into its component parts ? determining what type of statement it is (query, DML, DDL) and performing various checks on it.
這是Oracle處理所有語句的第一步,解析就是將使用者提交的語句(根據一定的規則)分成不同的元件,來確定這條語句是什麼型別的語句(query,查詢,DML,資料操縱語言,DDL還是資料定義語言),以對這條語句執行各種不同的語法檢測.
The parsing process performs two main functions:
解析過程主要有一下兩個功能.
1. Syntax Check: is the statement a valid one? Does it make sense given the SQL grammar documented in the SQL Reference Manual. Does it follow all of the rules for SQL.
語法檢查,這條語句是否合理? 它是否符合SQL語法文件<
2. Semantic Analysis: Going beyond the syntax ? is the statement valid in light of the objects in the database (do the tables and columns referenced exist). Do you have access to the objects ? are the proper privileges in place? Are there ambiguities in the statement ? for example if there are two tables T1 and T2 and both have a column X, the query ?select X from T1, T2 where ?? is ambiguous, we don?t know which table to get X from. And so on.
語義分析: 已經處理完語法檢查了嗎? 這條語句是否正確的引用了資料庫中物件(是否語句中所有的表和欄位都存在). 是否有訪問這些物件的許可權? 是不是對應的許可權都有效(主要指role對應的許可權吧,)? 比如是否有如下的兩個表T1,T2,而這兩個表有相同的欄位名column X,而查詢語句 ? select X from T1,T2 where ??,(沒有明確指定列名),我們無法知道從哪個表去取出欄位X的值,以及類似的一系列問題.
So, you can think of parsing as basically a two step process, that of a syntax check to check the validity of the statement and that of a semantic check ? to ensure the statement can execute properly. The difference between the two types of checks are hard for you to see ? Oracle does not come back and say ?it failed the syntax check?, rather it returns the statement with a error code and message. So for example, this statement fails with a syntax error:
因此,你可以認為解析基本上是由這兩個步驟組成的: 檢查語句有效性的語法檢查和確保語句能夠正常執行的語義檢查.這兩種檢查的區別就是你所要說的硬解析了.Oracle不會特別的指出這條語句沒有透過語法檢查,它給你返回這條語句對應的錯誤程式碼和錯誤資訊. 比如: 下面這條語句沒有透過語法檢查.複製內容到剪貼簿程式碼:
SQL> select from where 2;
select from where 2
*
ERROR at line 1:
ORA-00936: missing expression
While this statement failed with a semantic error ? if the table NOT_A_TABLE existed and we had permission to access it, this statement would have succeeded:
而這條語句沒有透過語義檢查? 如果表NOT_A_TABLE存在,並且我們具有訪問這個表的許可權,這條語句就會正確執行了.複製內容到剪貼簿程式碼:
SQL> select * from not_a_table;
select * from not_a_table
*
ERROR at line 1:
ORA-00942: table or view does not exist
That is the only way to really tell the difference between a semantic and syntactic error ? if the statement COULD have executed given the proper objects and privileges, you had a semantic error, otherwise if the statement could not execute under any circumstances, you have a syntax error. Regardless ? Oracle will not execute the statement for you!
只是我能用來解釋語法錯誤和語義錯誤的唯一的辦法了.如果在賦予合適的物件和許可權的情況下,這條語句確實能夠執行的話,我們稱之為語義錯誤,否則,如果這條語句在任何條件下都不能執行的話,我們就稱之為語法錯誤.無論如何,Oracle都不會為你執行這條語句.
解析中的下一個步驟就是檢查我們現在正在解析的語句是否已經被其他的session執行過,在這一步我們可能很幸運,我們可以跳過下面的兩個步驟: 語句的最佳化(生成執行計劃) 和 生成執行編碼. 如果我們能夠跳過這兩個步驟,我們就實現了一般意義上的軟解析, 我們必須解析,最佳化,併為這條語句生成執行計劃.這個特性(distinction)非常重要,當我們開發應用程式的時候,我們會希望大部分的語句都是軟解析的,以跳過最佳化和生成編碼的步驟,因為他們和爭用(序列化,)(contention)一樣,都是非常消耗CPU的操作.如果我們必須硬解析我們語句的大部分的話,在某些情況下我們的系統就會執行的很慢,並不是任何時候(在olap,dss系統應該是個例外吧)
在Oracle中共享SQL的方式是透過共享池--SGA中的一塊記憶體(由Oracle系統來維護)--實現的。我們在第五章中討論了這個主題,並且會在查詢處理的章節再次討論這個主題,當Oracle已經解析了這條語句,並且已經透過語法和語義檢查的時候,Oracle就會在SGA的shared pool(共享池)元件中查詢,看看是否已經有一個完全一樣的語句已經被另外一個session執行過。因為語句已經透過了oracle的語義檢查,並且oracle已經計算出:
具體涉及到哪些表.
我們擁有訪問對應表的個相應許可權.等等...
現在,可以在所有已經經過解析和最佳化並且生成的可執行編碼的SQL語句搜尋,來看看對應的語句是否已經經過解析。
can you explain what means the default value (0) of session_ casched_cursor parameter? Oracle always has a cache of sqls in sga and size of this cache is determinated through init.ora parameter shared_pool_size.
tom:你能不能給我解釋一下,session_cashed_cursor(預設值為0)引數的含義,Oracle在SGA中始終保持一個sql語句的快取,這個快取的大小是由初始化引數shared_pool_size的大小決定的。
The default value of ZERO means that by default, ZERO cursors will be cached for your session.
預設值為0表示,在預設情況下,Oracle不會給你的session快取遊標.
them there. Session Cached Cursors can remove the need to have to "ind" them. Consider this example that shows the difference spent when soft parsing without session cached cursors vs soft parsing WITH session cached cursors:
他們會被快取在共享池(Shared Pool)中,但是你的session必須在共享池中去查詢他們,session cached cursors可以省略掉去共享池中查詢這一步。下面這個例子給你演示了沒有快取遊標和快取了遊標之後軟解析之間的差別和系統消耗資源的情況
ops$[email]tkyte@ORA817DEV.US.ORACLE.COM[/email]> create table emp as select * from scott.emp;
Table created.
name varchar2(80), value int );
Table created.
2 as select 'STAT...' || a.name name, b.value
3 from v$statname a, v$mystat b
4 where a.statistic# = b.statistic#
5 union all
6 select 'LATCH.' || name, gets
7 from v$latch;
ops$[email]tkyte@ORA817DEV.US.ORACLE.COM[/email]> column name format a40
ops$[email]tkyte@ORA817DEV.US.ORACLE.COM[/email]> declare
2 l_start number;
3 l_cnt number;
4 begin
5 execute immediate 'alter session set session_cached_cursors=0';
6 insert into run_stats select 'before', stats.* from stats;
7
8 l_start := dbms_utility.get_time;
9 for i in 1 .. 1000
10 loop
11 execute immediate 'select count(*) from emp' into l_cnt;
12 end loop;
13 dbms_output.put_line( (dbms_utility.get_time-l_start) || ' hsecs' );
14
15 execute immediate 'alter session set session_cached_cursors=100';
16 insert into run_stats select 'after 1', stats.* from stats;
17
18 l_start := dbms_utility.get_time;
19 for i in 1 .. 1000
20 loop
21 execute immediate 'select count(*) from emp' into l_cnt;
22 end loop;
23 dbms_output.put_line( (dbms_utility.get_time-l_start) || ' hsecs' );
24
25 insert into run_stats select 'after 2', stats.* from stats;
26 end;
27 /
45 hsecs
35 hsecs
were no hard parses going on. But the real good news is:
因此,在session中快取遊標可以執行的更快(我執行了好幾次,沒有硬解析的發生),真正可喜的訊息是:
ops$[email]tkyte@ORA817DEV.US.ORACLE.COM[/email]> select a.name, b.value-a.value run1,
c.value-b.value run2,
2 ( (c.value-b.value)-(b.value-a.value)) diff
3 from run_stats a, run_stats b, run_stats c
4 where a.name = b.name
5 and b.name = c.name
6 and a.runid = 'before'
7 and b.runid = 'after 1'
8 and c.runid = 'after 2'
9 and (c.value-a.value) > 0
10 and (c.value-b.value) <> (b.value-a.value)
11 order by abs( (c.value-b.value)-(b.value-a.value))
12 /
---------------------------------------- ---------- ---------- ----------
LATCH.checkpoint queue latch 3 4 1
LATCH.redo allocation 30 31 1
STAT...consistent gets 5088 5089 1
STAT...deferred (CURRENT) block cleanout 2 3 1
applications
STAT...enqueue releases 10 9 -1
STAT...execute count 1015 1014 -1
STAT...opened cursors cumulative 1015 1014 -1
STAT...parse count (total) 1015 1014 -1
STAT...session cursor cache count 0 1 1
STAT...redo entries 28 27 -1
STAT...recursive calls 1180 1179 -1
STAT...physical reads 1 0 -1
LATCH.direct msg latch 2 0 -2
LATCH.session queue latch 2 0 -2
LATCH.done queue latch 2 0 -2
STAT...free buffer requested 8 6 -2
STAT...enqueue requests 11 9 -2
LATCH.messages 3 0 -3
STAT...db block changes 47 44 -3
LATCH.redo writing 3 0 -3
LATCH.ksfv messages 4 0 -4
STAT...session logical reads 17128 17123 -5
LATCH.row cache objects 184 178 -6
STAT...db block gets 12040 12034 -6
STAT...parse time elapsed 9 3 -6
STAT...parse time cpu 13 4 -9
STAT...recursive cpu usage 51 38 -13
LATCH.cache buffers chains 34315 34335 20
STAT...redo size 23900 24000 100
STAT...session cursor cache hits 3 1002 999
LATCH.shared pool 2142 1097 -1045
LATCH.library cache 17361 2388 -14973
see the significantly REDUCED number of LATCH counts on the library and shared pool. Since a latch is a lock, a lock is a serialization device, serialization
implies WAITS -- using the session cached cursors will increase scalability and performance as you add more and more users. Its not only FASTER, but more scalable as well...
看到庫快取和共享池中鎖存(Latch)數目的明顯的下降了嗎,因為鎖存(Latch)就是鎖(Lock),而鎖(Lock)就是隻能序列執行的裝置,序列就意味著等待--使用session快取的遊標可以提高系統的擴充套件性(scalability)和效能,當你的系統的使用者數不斷增加的時候,它不僅可以執行的更加快捷,而且可以提高了系統的擴充套件性。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/9399028/viewspace-682179/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Dockerfile - 引數與詳解Docker
- ajax 引數詳解
- OGG引數詳解
- java 之泛型與可變引數詳解Java泛型
- lsblk命令引數詳解
- Flink Checkpoint 引數詳解
- 函式引數詳解函式
- tar命令引數詳解
- Nginx編譯引數大全 configure引數中文詳解Nginx編譯
- pg_settings引數詳解
- 常用的 wget 引數詳解wget
- find 命令的引數詳解
- Oracle GoldenGate常用引數詳解OracleGo
- oracle rac 核心引數詳解Oracle
- variables_order引數詳解
- SQL*Plus Set引數詳解SQL
- Prometheus hashmod 配置引數詳解Prometheus
- ansible.cfg 配置引數詳解
- Pandas read_csv 引數詳解
- Nginx 配置檔案引數詳解Nginx
- curl常用引數詳解及示例
- Redis日常運維-引數詳解Redis運維
- expdp/impdp 詳細引數解釋
- JQuery中$.ajax()方法引數詳解jQuery
- plt.figure()引數使用詳解
- Oracle:open_cursorsOracle
- ORACLE中Cursor_sharing引數詳解Oracle
- MySQL relay log 詳細引數解釋MySql
- 定時任務@Scheduled引數詳解
- 轉載-詳解功率MOS管引數
- caffe網路各層引數詳解
- composer.json 檔案引數詳解JSON
- C語言可變引數詳解C語言
- consul配置引數大全、詳解、總結
- SwaggerAPI註解詳解,以及註解常用引數配置SwaggerAPI
- SpringBoot魔法堂:@MatrixVariable引數註解使用詳解Spring Boot
- HarmonyOS Next加解密演算法中的引數與模式詳解解密演算法模式
- 2、flask-run啟動引數詳解Flask
- js-arguments 函式引數物件詳解JS函式物件