日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

共享SQL语句减少硬解析

發(fā)布時(shí)間:2025/3/20 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 共享SQL语句减少硬解析 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
這篇文章是參考甲骨論老相老師所做的教學(xué)視頻:
http://v.youku.com/v_show/id_XMzkyMTczMTQ4.html
所做的學(xué)習(xí)筆記:

接上文:
http://nvd11.blog.163.com/blog/static/200018312201301875752730/
sql 是在shared Pool里面解析成執(zhí)行計(jì)劃的.

如圖:



??????? 1.什么是SQL語(yǔ)句共享

??????? sql 語(yǔ)句傳入shared pool后, 會(huì)被先轉(zhuǎn)換成ASCII碼, 然后經(jīng)過(guò)一系列運(yùn)算,其中包括HASH運(yùn)算,得出HASH值,然后得出一串?dāng)?shù)字,并包含1個(gè)內(nèi)存鏈chain號(hào)碼.

??????? Server Process 就會(huì)拿著chain號(hào)碼和HASH號(hào)碼,到Library cache上找到對(duì)應(yīng)的內(nèi)存鏈chain, 然后遍歷上面的chunk(比較Hash值), 如果有1個(gè)chunk的Hash與之相同,則證明這條sql曾經(jīng)被硬解析過(guò), 就直接可以拿出對(duì)應(yīng)執(zhí)行計(jì)劃, 這就是軟解析.

???????? 我們也可以說(shuō)這條sql與之前硬解析過(guò)的sql共享了.

??????? 如果找不到hash值相同的chunk,? 則認(rèn)為這條sql未被硬解析過(guò), 就要執(zhí)行上圖的動(dòng)作2,進(jìn)行硬解析.

??????? 所以可以看出,那個(gè)HASH值十分重要, 而hash值是由ASCII碼運(yùn)算出來(lái)的, 所以共享sql之間的ASCII碼要相同.

??????? 而ASCII是由SQL語(yǔ)句的字符決定的.? 所以兩條共享sql語(yǔ)句的每個(gè)字符要相同. 而且大小寫都要相同

??????? 舉個(gè)例子: 下面3條語(yǔ)句
??????? select /*comment_1*/ count(1) from dba_tables where table_name = 'EMP';
??????? select /*comment_1*/ count(1) from dba_tables where table_name = 'DEPT';
??????? select /*comment_1*/ count(1) from? dba_tables where table_name = 'DEPT';

?????? 首先,很明顯 第一條語(yǔ)句和第二條語(yǔ)句不相同, 因?yàn)镋MP 和 DEPT 是兩個(gè)不同的字符
?????? 第二條和第三條呢?? 也不相同, 因?yàn)榈诙l from 與 dba_tables直接只有1個(gè)空格, 而第3條有2個(gè)! 所以他們的ASCII碼不同,所以規(guī)范編寫SQL語(yǔ)句很重要啊.

?===============================================分割線===============================
2.判斷SQL語(yǔ)句有無(wú)共享
下面我分別執(zhí)行上面3條語(yǔ)句1次
??
注意第2條和第3條語(yǔ)句的空格區(qū)別哦

然后可以去v$sql 去查看已執(zhí)行過(guò)的sql語(yǔ)句:
?select sql_id,sql_text,executions from v$sql where sql_text like '%comment_1%';

可以看出這3條sql語(yǔ)句分別被執(zhí)行了1次??? (因?yàn)檎{(diào)整顯示格式, 查詢v$sql的這條執(zhí)行3次)
也就說(shuō)進(jìn)行了3次硬解析.

其實(shí)每執(zhí)行1條sql語(yǔ)句, 都會(huì)分配1個(gè)sql_id(參見(jiàn)上圖),上面3條語(yǔ)句被分配3個(gè)sql_id, 所以oracle認(rèn)為上面3條語(yǔ)句是不一樣的.

所以O(shè)racle中sql語(yǔ)句要相同:
則所有字符要一樣, 包括空格,空行,回車...

例如, 如果要第3條語(yǔ)句與第一條語(yǔ)句共享, 則要去掉from 和 dba_tables之間的1個(gè)空格:
我們?cè)趫?zhí)行一次:
?
可發(fā)現(xiàn),v$sql中并沒(méi)有多出一個(gè)sql_id, 只不過(guò)第一條的執(zhí)行次數(shù)變成了2,? 也就是說(shuō)第4次執(zhí)行的那條跟第一條的sql_id是一樣的,因?yàn)樗鼈兊淖址耆粯?

那么第一條和第二條sql能不能共享呢, 因?yàn)闂l件'EMP' 跟 'DEPT' 完全不同啊, 貌似是個(gè)硬傷.

方法是有的:
就是用1個(gè)相同名字的變量, 分別賦值'EMP'和'DEPT'各執(zhí)行一次, 因?yàn)樽兞棵嗤?
做個(gè)例子:

寫1個(gè) sql 腳本如下:
?

上面的腳本會(huì)插入11行數(shù)據(jù)進(jìn)入表test, 雖然每一行的值都是不同, 但是我們可以用變量? i來(lái)裝載它.
然后使用 execute 來(lái)執(zhí)行sql語(yǔ)句.

下面執(zhí)行這個(gè)腳本:


在查看v$sql 視圖:
?
可以見(jiàn)到11次sql語(yǔ)句之分配了1個(gè) sql_id , 用:1 來(lái)取代實(shí)際的值. 也就是說(shuō)11條insert語(yǔ)句之產(chǎn)生1此硬解析, 其余10次是軟解析,成功共享SQL.
這個(gè)方法很重要, 可以想象一下銀行業(yè)務(wù), 可能經(jīng)常大量地使用同一條sql語(yǔ)句,但是參數(shù)次次都不同, 如果在寫程序時(shí)不使用綁定變量,則會(huì)產(chǎn)生大量的硬解析,? 而使用了綁定變量去取代參數(shù), 就能避免這個(gè)情況!

所以總結(jié)一下共享SQL的關(guān)鍵:

1. 嚴(yán)格統(tǒng)一書寫風(fēng)格
2. 使用綁定變量


提醒下, v$sql實(shí)在上就是緩存在shared pool里的sql語(yǔ)句信息.
可以用alter system flush shared pool 來(lái)清空v$sql, 不過(guò)接下來(lái)就大量硬解 你懂的.


?===============================================分割線===============================

3.如何找出未被共享(硬解析)的sql語(yǔ)句:

原理都好簡(jiǎn)單, 因?yàn)槿绻粭lsql未被共享,則這條sql在v$sql里的執(zhí)行次數(shù)為1.
所以只需查找v$sql
select sql_id, sql_fulltext,executions from v$sql where sql_text like '%from t%' and executions = 1 order by sql_text ;

注意綠色高亮部分根據(jù)實(shí)際情況修改

order by 排序很重要啊, 因?yàn)橛行﹕ql的確只被用戶執(zhí)行了一次, 用order by就可找出那些類似的sql,而被硬解析多次了~

下面做個(gè)例子,
修改一下上面的腳本, 令到循環(huán)中每次執(zhí)行的語(yǔ)句都不一樣(參數(shù)不一樣)
如下圖, 注意右邊是修改后的:
執(zhí)行了900幾次..
?
然后執(zhí)行這個(gè)修改后的腳本:
?
接下來(lái)用
select sql_id, sql_fulltext,executions from v$sql where sql_text like '%insert%' and executions = 1 order by sql_text;
查看 未被共享的語(yǔ)句.
?

接下來(lái)去查看導(dǎo)出來(lái)的log文件, 通常就可以分析出哪些sql語(yǔ)句未被共享而被執(zhí)行大量硬解析了..
?
這是1個(gè)很經(jīng)典的查找未被共享sql語(yǔ)句的方法, 用于數(shù)據(jù)庫(kù)優(yōu)化.

===============================================分割線===============================

4. 設(shè)置cursor_sharing參數(shù)
找到未被共享的sql語(yǔ)句后怎么做呢, 一般會(huì)交給程序員,讓他們修改.

但是做過(guò)碼農(nóng)的都知道, 程序里的代碼有些時(shí)候不是那么好改了,有時(shí)真的牽一發(fā)而動(dòng)全身啊..

那改不了怎么辦.

其實(shí)還有1個(gè)辦法是設(shè)置oracle的一個(gè)參數(shù): cursor_sharing
我們先查看當(dāng)前默認(rèn)的參數(shù)值是什么:
?
可以見(jiàn)到當(dāng)前值是EXACT, 代表什么意思呢, 我們?nèi)racle官方文檔查下:

CURSOR_SHARING determines what kind of SQL statements can share the same cursors.

Values:

  • FORCE

    Allows the creation of a new cursor if sharing an existing cursor, or if the cursor plan is not optimal.

  • EXACT

    Only allows statements with identical text to share the same cursor.

可以見(jiàn)到, 游標(biāo)共享參數(shù)決定了什么情況下可以共享SQL

EXACT : 只有當(dāng)sql語(yǔ)句完全一樣才共享sql

關(guān)鍵是FORCE了:

首先共享SQL失敗原因有兩種:

1.是書寫不規(guī)范(大小寫, 空格)

2. 沒(méi)有用綁定變量去取代參數(shù).


對(duì)于第一種原因的sql共享失敗, 這個(gè)cursor_sharing設(shè)置也沒(méi)辦法解決, 不過(guò)很容易交給程序員解決.

而將cursor_sharing設(shè)置為force 可以解決第2種情況,


我們測(cè)試一下:

首先將cursor_sharing 設(shè)置為force

?
跟住清空shared pool緩存:
?

然后我們?cè)賵?zhí)行一次上面執(zhí)行過(guò)的那個(gè)腳本:

?
執(zhí)行:
?
我們?cè)偃ゲ榭磛$sql..
但是由這個(gè)測(cè)試來(lái)講是無(wú)效果的... 而老相在視頻里沒(méi)提供測(cè)試..
可以見(jiàn)到 sql語(yǔ)句并沒(méi)有共享, 依然是沒(méi)一條insert 語(yǔ)句分配1個(gè)sql id.
?


于是我私人再做多個(gè)測(cè)試,睇下這個(gè)參數(shù)會(huì)不會(huì)影響硬解析的數(shù)量.


首先將cursor_sharing設(shè)置成默認(rèn)的'EXACT', 并清空shared pool緩存.



接著查看當(dāng)前硬解析和軟解析數(shù)量:
?
可以記下:
當(dāng)前已經(jīng)發(fā)生過(guò)的解析數(shù)量總數(shù)為: 611230
其中硬解析數(shù)量為: 35774

這時(shí)我們執(zhí)行一次insert腳本:
?
再次查看解析數(shù)量:
?
其中解析數(shù)量總數(shù)增加了? 613301 - 611230 =? 2071
而硬解析數(shù)量增加了 36778 - 35774 =? 1004
可以看出硬解析的數(shù)量是相當(dāng)接近 腳本中循環(huán)執(zhí)行的insert 語(yǔ)句數(shù)量的!

這是我們將cursor_sharing 設(shè)置為Force
并且清空shared pool


再查看當(dāng)前的解析數(shù)量:
?
?當(dāng)前已經(jīng)發(fā)生過(guò)的解析數(shù)量總數(shù)為: 616473
其中硬解析數(shù)量為: 37432


這時(shí)我們?cè)俅螆?zhí)行一次insert腳本:
?
再次查看解析數(shù)量:
??
其中解析數(shù)量總數(shù)增加了? 618008 - 616473 =? 1535
而硬解析數(shù)量增加了 38511 - 37432 =? 1079

尼瑪硬解析數(shù)量反而增加了


我覺(jué)得原因是可能這個(gè)參數(shù)對(duì)我腳步那種sql 無(wú)作用, 至于到底會(huì)影響哪些sql共享, 以后再研究了...







?







??????


??????
?



總結(jié)

以上是生活随笔為你收集整理的共享SQL语句减少硬解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。