說到軟解析(soft prase)和硬解析(hard prase)就不能不說一下Oracle對sql的處理過程當你發出一條sql語句交付Oracle在執行和獲取結果前Oracle對此sql將進行幾個步驟的處理過程
語法檢查(syntax check)
檢查此sql的拼寫是否語法
語義檢查(semantic check)
諸如檢查sql語句中的訪問對象是否存在及該用戶是否具備相應的權限
對sql語句進行解析(prase)
利用內部算法對sql進行解析生成解析樹(parse tree)及執行計劃(execution plan)
執行sql返回結果(execute and return)
其中軟硬解析就發生在第三個過程裡
Oracle利用內部的hash算法來取得該sql的hash值然後在library cache裡查找是否存在該hash值
假設存在則將此sql與cache中的進行比較
假設相同就將利用已有的解析樹與執行計劃而省略了優化器的相關工作這也就是軟解析的過程
誠然如果上面的個假設中任有一個不成立那麼優化器都將進行創建解析樹生成執行計劃的動作這個過程就叫硬解析
創建解析樹生成執行計劃對於sql的執行來說是開銷昂貴的動作所以應當極力避免硬解析盡量使用軟解析
這就是在很多項目中倡導開發設計人員對功能相同的代碼要努力保持代碼的一致性以及要在程序中多使用綁定變量的原因
/****************************************************/
大家都在說在Sql中使用了Bind Var(綁定變量)會提高不少性能那他到底是如何提高性能的呢?
使用了Bind Var能提高性能主要是因為這樣做可以盡量避免不必要的硬分析(Hard Parse)而節約了時間同時節約了大量的CPU資源
當一個Client提交一條Sql給Oracle後Oracle 首先會對其進行解析(Parse)然後將解析結果提交給優化器(Optimiser)來進行優化而取得Oracle認為的最優的Query Plan然後再按照這個最優的Plan來執行這個Sql語句(當然在這之中如果只需要軟解析的話會少部分步驟)
但是當Oracle接到 Client提交的Sql後會首先在共享池(Shared Pool)裡面去查找是否有之前已經解析好的與剛接到的這一個Sql完全相同的Sql(注意這裡說的是完全相同既要求語句上的字符級別的完全相同又要求涉及的對象也必須完全相同)當發現有相同的以後解析器就不再對新的Sql在此解析而直接用之前解析好的結果了這裡就節約了解析時間以及解析時候消耗的CPU資源尤其是在OLTP中運行著的大量的短小Sql效果就會比較明顯了因為一條兩條Sql的時間可能不會有多少感覺但是當量大了以後就會有比較明顯的感覺了
上面說到了硬解析(Hard Parse)那這個Hard Parse到底是個啥呢?
Parse主要分為三種
Hard Parse (硬解析)
Soft Parse (軟解析)
Soft Soft Parse(好像有些資料中並沒有將這個算在其中)
Hard Parse就是上面提到的對提交的Sql完全重新從頭進行解析(當在Shared Pool中找不到時候將會進行此操作)總共有一下個執行步驟
語法分析
權限與對象檢查
在共享池中檢查是否有完全相同的之前完全解析好的—如果存在直接跳過和運行Sql(此時算soft parse)
選擇執行計劃
產生執行計劃
Soft Parse就如果是在Shared Pool中找到了與之完全相同的Sql解析好的結果後會跳過Hard Parse中的後面的兩個步驟
Soft Soft Parse實際上是當設置了session_cursor_cache這個參數之後Cursor被直接Cache在當前Session的PGA中的在解析的時候只需要對其語法分析權限對象分析之後就可以轉到PGA中查找了如果發現完全相同的Cursor就可以直接去取結果了也就就是實現了 Soft Soft Parse
不過在計算解析次數的時候是只計算Hard Parse和Soft Parse的(其實Soft Soft Parse好像也並不能算是做了Parse )Soft Parse百分比計算Round(*(hprs/prse)) [hprs硬解析次數prse解析次數] Parse比率計算 Round(*(prse/exec) ) [exec執行次數]
/*****************************************************/
quote from difference between soft parse and hard parse
Thanks for the question regarding difference between soft parse and hard parse version
originally submitted on Jan : Eastern US time last updated Aug :
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這是一個很長的解釋是從我與幾個同事一起合著的新書<<開始學習Oracle編程>>中提取出來的
Parsing解析
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解析過程主要有一下兩個功能
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語法文檔<>的相關語法是不是符合SQL語句的所有規則
o 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 T and T and both have a column X the query ?select X from T T where ?? is ambiguous we don?t know which table to get X from And so on 語義分析 已經處理完語法檢查了嗎? 這條語句是否正確的引用了數據庫中對象(是否語句中所有的表和字段都存在) 是否有訪問這些對象的權限? 是不是對應的權限都有效(主要指role對應的權限吧)? 比如是否有如下的兩個表TT而這兩個表有相同的字段名column X而查詢語句 ? select X from TT 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不會特別的指出這條語句沒有通過語法檢查它給你返回這條語句對應的錯誤代碼和錯誤信息 比如 下面這條語句沒有通過語法檢查
Code
SQL> select from where ;
select from where
*
ERROR at line :
ORA: 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存在並且我們具有訪問這個表的權限這條語句就會正確執行了
Code
SQL> select * from not_a_table;
select * from not_a_table
*
ERROR at line :
ORA: 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都不會為你運行這條語句
The next step in the parse operation is to see if the statement we are currently parsing has already in fact been processed by some other session If it has ? we may be in luck here we can skip the next two steps in the process that of optimization and row source generation If we can skip these next two steps in the process we have done what is known as a Soft Parse ? a shorter process to getting our query going If we cannot if we must do all of the steps we are performing what is known as a Hard Parse ? we must parse optimize generate the plan for the query This distinction is very important When developing our applications we want a very high percentage of our queries to be Soft Parsed ? to be able to skip the optimize/generate phases ? as they are very CPU intensive as well as a point of contention (serialization) If we have to Hard Parse a large percentage of our queries our system will function slowly and in some cases ? not at all
解析中的下一個步驟就是檢查我們現在正在解析的語句是否已經被其他的session執行過在這一步我們可能很幸運我們可以跳過下面的兩個步驟 語句的優化(生成執行計劃) 和 生成執行編碼 如果我們能夠跳過這兩個步驟我們就實現了一般意義上的軟解析 我們必須解析優化並為這條語句生成執行計劃這個特性(distinction)非常重要當我們開發應用程序的時候我們會希望大部分的語句都是軟解析的以跳過優化和生成編碼的步驟因為他們和爭用(串行化)(contention)一樣都是非常消耗CPU的操作如果我們必須硬解析我們語句的大部分的話在某些情況下我們的系統就會運行的很慢並不是任何時候(在olapdss系統應該是個例外吧)
The way this sharing of SQL in Oracle is accomplished is via the shared pool a piece of memory in the SGA maintained by Oracle We covered this topic in chapter but will revisit it again in the context of processing a query After Oracle parses the query and it passes the syntax and semantic checks ? it will look in the shared pool component of the SGA to see if that same exact query has already been processed by another session Since it has performed the semantic check it has already figured out
在Oracle中共享SQL的方式是通過共享池——SGA中的一塊內存(由Oracle系統來維護)——實現的我們在第五章中討論了這個主題並且會在查詢處理的章節再次討論這個主題當Oracle已經解析了這條語句並且已經通過語法和語義檢查的時候Oracle就會在SGA的shared pool(共享池)組件中查詢看看是否已經有一個完全一樣的語句已經被另外一個session執行過因為語句已經通過了oracle的語義檢查並且oracle已經計算出
o Exactly what tables are involved具體涉及到哪些表
o That we have access to the tables (the proper privileges are there)
我們擁有訪問對應表的個相應權限等等……
And so on Now it can look at all of the queries in the shared pool that have already been parsed/optimized and generated to see if the work has already been done現在可以在所有已經經過解析和優化並且生成的可執行編碼的SQL語句搜索來看看對應的語句是否已經經過解析
Soft Parse and session_cashed_cursor parameter January Reviewer A reader軟解析與session_cashed_cursor參數
can you explain what means the default value () of session_ casched_cursor parameter? Oracle always has a cache of sqls in sga and size of this cache is determinated through initora parameter shared_pool_size
tom 你能不能給我解釋一下session_cashed_cursor(默認值為)參數的含義Oracle在SGA中始終保持一個sql語句的緩存這個緩存的大小是由初始化參數shared_pool_size的大小決定的
FollowupThe default value of ZERO means that by default ZERO cursors will be cached for your session
默認值為表示在默認情況下Oracle不會給你的session緩存游標
They will be cached in the shared pool —— but your session will have to find them there Session Cached Cursors can remove the need to have to find 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可以省略掉去共享池中查找這一步下面這個例子給你演示了沒有緩存游標和緩存了游標之後軟解析之間的差別和系統消耗資源的情況
Code
ops$[email]tkyte@ORADEVUSORACLECOM[/email]> create table emp as select * from scottemp;
Table created
ops$[email]tkyte@ORADEVUSORACLECOM[/email]> create table run_stats ( runid varchar()
name varchar() value int );
Table created
ops$[email]tkyte@ORADEVUSORACLECOM[/email]> create or replace view stats
as select STAT || aname name bvalue
from v$statname a v$mystat b
where astatistic# = bstatistic#
union all
select LATCH || name gets
from v$latch;
View created
ops$[email]tkyte@ORADEVUSORACLECOM[/email]> column name format a
ops$[email]tkyte@ORADEVUSORACLECOM[/email]> declare
l_start number;
l_cnt number;
begin
execute immediate alter session set session_cached_cursors=;
insert into run_stats select before stats* from stats;
l_start := dbms_utilityget_time;
for i in
loop
execute immediate select count(*) from emp into l_cnt;
end loop;
dbms_outputput_line( (dbms_utilityget_timel_start) || hsecs );
execute immediate alter session set session_cached_cursors=;
insert into run_stats select after stats* from stats;
l_start := dbms_utilityget_time;
for i in
loop
execute immediate select count(*) from emp into l_cnt;
end loop;
dbms_outputput_line( (dbms_utilityget_timel_start) || hsecs );
insert into run_stats select after stats* from stats;
end;
/
hsecs
hsecs
PL/SQL procedure successfully completed
so session cached cursors RAN faster (i ran this a couple of times there were no hard parses going on But the real good news is因此在session中緩存游標可以運行的更快(我運行了好幾次沒有硬解析的發生)真正可喜的消息是
Code
ops$[email]tkyte@ORADEVUSORACLECOM[/email]> select aname bvalueavalue run
cvaluebvalue run
( (cvaluebvalue)(bvalueavalue)) diff
from run_stats a run_stats b run_stats c
where aname = bname
and bname = cname
and arunid = before
and brunid = after
and crunid = after
and (cvalueavalue) >
and (cvaluebvalue) <> (bvalueavalue)
order by abs( (cvaluebvalue)(bvalueavalue))
/
NAME RUN RUN DIFF
LATCHcheckpoint queue latch
LATCHredo allocation
nsistent gets
STATdeferred (CURRENT) block cleanout
applications
STATcalls to get snapshot scn: kcmgss
STATenqueue releases
STATexecute count
STATopened cursors cumulative
STATparse count (total)
STATsession cursor cache count
STATredo entries &nb
From:http://tw.wingwit.com/Article/program/Oracle/201311/18466.html