濮阳杆衣贸易有限公司

主頁 > 知識庫 > Oracle硬解析和軟解析的區(qū)別分析

Oracle硬解析和軟解析的區(qū)別分析

熱門標簽:N個你智能電銷機器人 外呼電話系統(tǒng)用卡嗎 廣東營銷智能外呼系統(tǒng)商家 七日殺a19.5全地圖標注 車瑪仕極限運動場所地圖標注 騰訊地圖標注要費用嗎 高德地圖標注公司名字大全 地圖標注怎么保存 電渠外呼系統(tǒng)

一、摘要

Oracle硬解析和軟解析是我們經(jīng)常遇到的問題,所以需要考慮何時產(chǎn)生軟解析何時產(chǎn)生硬解析,如何判斷

SQL的執(zhí)行過程

當發(fā)布一條SQL或PL/SQL命令時,Oracle會自動尋找該命令是否存在于共享池中來決定對當前的語句使用硬解析或軟解析。

通常情況下,SQL語句的執(zhí)行過程如下:

Step1. SQL代碼的語法(語法的正確性)及語義檢查(對象的存在性與權(quán)限)。

Step2. 將SQL代碼的文本進行哈希得到哈希值。

Step3. 如果共享池中存在相同的哈希值,則對這個命令進一步判斷是否進行軟解析,否則到e步驟。

Step4. 對于存在相同哈希值的新命令行,其文本將與已存在的命令行的文本逐個進行比較。

    這些比較包括大小寫,字符串是否一致,空格,注釋等,如果一致,則對其進行軟解析,轉(zhuǎn)到步驟Step6,無需再次硬解析。

    否則到步驟Step5。

Step5. 硬解析,生成執(zhí)行計劃。

Step6. 執(zhí)行SQL代碼,返回結(jié)果。

二、軟解析

1.下面的三個查詢語句,不能使用相同的共享SQL區(qū)。盡管查詢的表對象使用了大小寫,但Oracle為其生成了不同的執(zhí)行計劃

select * from emp;

select * from Emp;

select * from EMP;

2.類似的情況,下面的查詢中,盡管其where子句empno的值不同,Oracle同樣為其生成了不同的執(zhí)行計劃      

select * from emp where empno=7369

select * from emp where empno=7788

3.在判斷是否使用硬解析時,所參照的對象及schema應(yīng)該是相同的,如果對象相同,而schema不同,則需要使用硬解析,生成不同的執(zhí)行計劃

sys@ASMDB> select owner,table_name from dba_tables where table_name like 'TB_OBJ%';
    OWNER             TABLE_NAME
    ------------------------------ ------------------------------
    USR1              TB_OBJ        --兩個對象的名字相同,當所有者不同
    SCOTT             TB_OBJ
usr1@ASMDB> select * from tb_obj;
scott@ASMDB> select * from tb_obj;   --此時兩者都需要使用硬解析以及走不同的執(zhí)行計劃

三、硬解析

硬解析即整個SQL語句的執(zhí)行需要完完全全的解析,生成執(zhí)行計劃。而硬解析,生成執(zhí)行計劃需要耗用CPU資源,以及SGA資源。在此不得不提的是對庫緩存中閂的使用。閂是鎖的細化,可以理解為是一種輕量級的串行化設(shè)備。當進程申請到閂后,則這些閂用于保護共享內(nèi)存的數(shù)在同一時刻不會被兩個以上的進程修改。在硬解析時,需要申請閂的使用,而閂的數(shù)量在有限的情況下需要等待。大量的閂的使用由此造成需要使用閂的進程排隊越頻繁,性能則逾低下。

1. 下面對上面的兩種情形進行演示

在兩個不同的session中完成,一個為sys帳戶的session,一個為scott賬戶的session,不同的session,其SQL命令行以不同的帳戶名開頭

如" sys@ASMDB> "  表示使用時sys帳戶的session," scott@ASMDB> "表示scott帳戶的session

sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;     
NAME           CLASS   VALUE
-------------------- ---------- ----------      --當前的硬解析值為569
parse count (hard)      64    569
scott@ASMDB> select * from emp;  
    sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;   
    NAME           CLASS   VALUE
    -------------------- ---------- ----------      --執(zhí)行上一個查詢后硬解析值為570,解析次數(shù)增加了一次
    parse count (hard)      64    570
scott@ASMDB> select * from Emp;
    sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;    
    NAME           CLASS   VALUE
    -------------------- ---------- ----------      --執(zhí)行上一個查詢后硬解析值為571
    parse count (hard)      64    571
scott@ASMDB> select * from EMP;
    sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;    
    NAME           CLASS   VALUE
    -------------------- ---------- ----------      --執(zhí)行上一個查詢后硬解析值為572
    parse count (hard)      64    572  
scott@ASMDB> select * from emp where empno=7369;    
    sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;
    NAME           CLASS   VALUE
    -------------------- ---------- ----------      --執(zhí)行上一個查詢后硬解析值為573
    parse count (hard)      64    573
scott@ASMDB> select * from emp where empno=7788;  --此處原來empno=7369,復(fù)制錯誤所致,現(xiàn)已更正為7788@20130905  
    sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;
    NAME           CLASS   VALUE
    -------------------- ---------- ----------     --執(zhí)行上一個查詢后硬解析值為574
    parse count (hard)      64    574

從上面的示例中可以看出,盡管執(zhí)行的語句存在細微的差別,但Oracle還是為其進行了硬解析,生成了不同的執(zhí)行計劃。即便是同樣的SQL語句,而兩條語句中空格的多少不一樣,Oracle同樣會進行硬解析。

四、硬解析改進 - 使用動態(tài)語句

1. 更改參數(shù)cursor_sharing

        參數(shù)cursor_sharing決定了何種類型的SQL能夠使用相同的SQL area

        CURSOR_SHARING = { SIMILAR | EXACT | FORCE }   

            EXACT      --只有當發(fā)布的SQL語句與緩存中的語句完全相同時才用已有的執(zhí)行計劃。

            FORCE      --如果SQL語句是字面量,則迫使Optimizer始終使用已有的執(zhí)行計劃,無論已有的執(zhí)行計劃是不是最佳的。

            SIMILAR   --如果SQL語句是字面量,則只有當已有的執(zhí)行計劃是最佳時才使用它,如果已有執(zhí)行計劃不是最佳則重新對這個SQL

                            --語句進行分析來制定最佳執(zhí)行計劃。

        可以基于不同的級別來設(shè)定該參數(shù),如ALTER SESSION, ALTER SYSTEM

sys@ASMDB> show parameter cursor_shar       --查看參數(shù)cursor_sharing
      NAME                 TYPE    VALUE
      ------------------------------------ ----------- ------------------------------
      cursor_sharing            string   EXACT
sys@ASMDB> alter system set cursor_sharing='similar';  --將參數(shù)cursor_sharing的值更改為similar
sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;  
      NAME           CLASS   VALUE
      -------------------- ---------- ----------    --當前硬解析的值為865
      parse count (hard)      64    865
scott@ASMDB> select * from dept where deptno=10;
sys@ASMDB> select name,class,value from v$sysstat where statistic#=331; 
      NAME           CLASS   VALUE
      -------------------- ---------- ----------    --執(zhí)行上一條SQL查詢后,硬解析的值變?yōu)?66
      parse count (hard)      64    866
scott@ASMDB> select * from dept where deptno=20;
sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;
      NAME           CLASS   VALUE
      -------------------- ---------- ----------    --執(zhí)行上一條SQL查詢后,硬解析的值沒有發(fā)生變化還是866
      parse count (hard)      64    866
sys@ASMDB> select sql_text,child_number from v$sql  -- 在下面的結(jié)果中可以看到SQL_TEXT列中使用了綁定變量:"SYS_B_0" 
      where sql_text like 'select * from dept where deptno%';
      SQL_TEXT                      CHILD_NUMBE
      -------------------------------------------------- ------------ 
      select * from dept where deptno=:"SYS_B_0"          0
sys@ASMDB> alter system set cursor_sharing='exact';    --將cursor_sharing改回為exact
      --接下來在scott的session 中執(zhí)行deptno=40 和的查詢后再查看sql_text,當cursor_sharing改為exact后,每執(zhí)行那個一次
      --也會在v$sql中增加一條語句
sys@ASMDB> select sql_text,child_number from v$sql        
      where sql_text like 'select * from dept where deptno%';
      SQL_TEXT                      CHILD_NUMBER
      -------------------------------------------------- ------------
      select * from dept where deptno=50              0   
      select * from dept where deptno=40              0
      select * from dept where deptno=:"SYS_B_0"          0
 
2. 使用綁定變量的方式

綁定變量要求變量名稱,數(shù)據(jù)類型以及長度是一致,否則無法使用軟解析

(1). 綁定變量(bind variable)是指在DML語句中使用一個占位符,即使用冒號后面緊跟變量名的形式,如下

            select * from emp where empno=7788    --未使用綁定變量

            select * from emp where empono=:eno   --:eno即為綁定變量

            在第二個查詢中,變量值在查詢執(zhí)行時被提供。該查詢只編譯一次,隨后會把查詢計劃存儲在一個共享池(庫緩存)中,以便以后獲取和重用這個查詢計劃。

(2). 下面使用了綁定變量,但兩個變量其實質(zhì)是不相同的,對這種情形,同樣使用硬解析

            select * from emp where empno=:eno;

            select * from emp where empno=:emp_no

           使用綁定變量時要求不同的會話中使用了相同的回話環(huán)境,以及優(yōu)化器的規(guī)則等


scott@ASMDB> create table tb_test(col int);   --創(chuàng)建表tb_test
scott@ASMDB> create or replace procedure proc1 --創(chuàng)建存儲過程proc1使用綁定變量來插入新記錄
as
begin
for i in 1..10000
loop
execute immediate 'insert into tb_test values(:n)' using i;
end loop;
end;
/
Procedure created.
scott@ASMDB> create or replace procedure proc2 --創(chuàng)建存儲過程proc2,未使用綁定變量,因此每一個SQL插入語句都會硬解析
as
begin
for i in 1..10000
loop
execute immediate 'insert into tb_test values('||i||')';
end loop;
end;
/
Procedure created.
scott@ASMDB> exec runstats_pkg.rs_start
PL/SQL procedure successfully completed.
scott@ASMDB> exec proc1;
PL/SQL procedure successfully completed.
scott@ASMDB> exec runstats_pkg.rs_middle;
PL/SQL procedure successfully completed.
scott@ASMDB> exec proc2;
PL/SQL procedure successfully completed.
scott@ASMDB> exec runstats_pkg.rs_stop(1000);
      Run1 ran in 1769 hsecs
      Run2 ran in 12243 hsecs       --run2運行的時間是run1的/1769≈倍
      run 1 ran in 14.45% of the time  
      Name                Run1   Run2   Diff
      LATCH.SQL memory manager worka    410   2,694   2,284
      LATCH.session allocation       532   8,912   8,380
      LATCH.simulator lru latch       33   9,371   9,338
      LATCH.simulator hash latch      51   9,398   9,347
      STAT...enqueue requests        31  10,030   9,999
      STAT...enqueue releases        29  10,030  10,001
      STAT...parse count (hard)       4  10,011  10,007  --硬解析的次數(shù),前者只有四次
      STAT...calls to get snapshot s    55  10,087  10,032
      STAT...parse count (total)      33  10,067  10,034
      STAT...consistent gets        247  10,353  10,106
      STAT...consistent gets from ca    247  10,353  10,106
      STAT...recursive calls      10,474  20,885  10,411
      STAT...db block gets from cach  10,408  30,371  19,963
      STAT...db block gets       10,408  30,371  19,963
      LATCH.enqueues            322  21,820  21,498  --閂的隊列數(shù)比較
      LATCH.enqueue hash chains      351  21,904  21,553
      STAT...session logical reads   10,655  40,724  30,069
      LATCH.library cache pin      40,348  72,410  32,062  --庫緩存pin
      LATCH.kks stats            8  40,061  40,053
      LATCH.library cache lock       318  61,294  60,976
      LATCH.cache buffers chains    51,851  118,340  66,489
      LATCH.row cache objects       351  123,512  123,161
      LATCH.library cache        40,710  234,653  193,943
      LATCH.shared pool         20,357  243,376  223,019
      Run1 latches total versus runs -- difference and pct
      Run1   Run2   Diff   Pct
      157,159  974,086  816,927 16.13%     --proc2使用閂的數(shù)量也遠遠多于proc1,其比值是.13% 
PL/SQL procedure successfully completed.
 

 (3). 使用綁定變量的好處

由上面的示例可知,在未使用綁定變量的情形下,不論是解析次數(shù),閂使用的數(shù)量,隊列,分配的內(nèi)存,庫緩存,行緩存遠遠高于綁定

變量的情況。因此盡可能的使用綁定變量避免硬解析產(chǎn)生所需的額外的系統(tǒng)資源。

綁定變量的優(yōu)點

減少SQL語句的硬解析,從而減少因硬解析產(chǎn)生的額外開銷(CPU,Shared pool,latch)。其次提高編程效率,減少數(shù)據(jù)庫的訪問次數(shù)。

綁定變量的缺點

 優(yōu)化器就會忽略直方圖的信息,在生成執(zhí)行計劃的時候可能不夠優(yōu)化。SQL優(yōu)化相對比較困難

五、總結(jié)

 1.盡可能的避免硬解析,因為硬解析需要更多的CPU資源,閂等。

 2.cursor_sharing參數(shù)應(yīng)權(quán)衡利弊,需要考慮使用similar與force帶來的影響。

 3.盡可能的使用綁定變量來避免硬解析。

標簽:長沙 玉樹 贛州 蘇州 棗莊 來賓 大興安嶺 遼寧

巨人網(wǎng)絡(luò)通訊聲明:本文標題《Oracle硬解析和軟解析的區(qū)別分析》,本文關(guān)鍵詞  Oracle,硬,解析,和,軟,的,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《Oracle硬解析和軟解析的區(qū)別分析》相關(guān)的同類信息!
  • 本頁收集關(guān)于Oracle硬解析和軟解析的區(qū)別分析的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    金阳县| 前郭尔| 通城县| 玉林市| 巫山县| 沙湾县| 鄂伦春自治旗| 长兴县| 正蓝旗| 金秀| 岳阳市| 赤城县| 措美县| 湘潭县| 民勤县| 凤台县| 黑水县| 游戏| 长子县| 商丘市| 康定县| 天气| 玉田县| 宜兰市| 青海省| 英超| 丹巴县| 延庆县| 庆阳市| 泌阳县| 乌拉特中旗| 确山县| 石渠县| 三河市| 宾阳县| 财经| 贡觉县| 宝应县| 洪江市| 鲁甸县| 云林县|