1、為什么要使用綁定變量
(1)SQL語(yǔ)句硬分析(Hard Parse)太多,嚴(yán)重消耗CPU資源,延長(zhǎng)了SQL語(yǔ)句總的執(zhí)行時(shí)間
SQL語(yǔ)句的執(zhí)行過程分幾個(gè)步驟:語(yǔ)法檢查、分析、執(zhí)行、返回結(jié)果。其中分析分為硬分析(Hard Parse)和軟分析(Soft Parse)。一條SQL語(yǔ)句通過語(yǔ)法檢查后,Oracle 會(huì)先去shared pool 中找是否有相同的sql,如果找著了,就叫軟分析,然后執(zhí)行SQL語(yǔ)句。硬分析主要是檢查該sql所涉及到的所有對(duì)象是否有效以及權(quán)限等關(guān)系,然后根據(jù)RBO或CBO模式生成執(zhí)行計(jì)劃,然后才執(zhí)行SQL語(yǔ)句。
可以看出,硬分析比軟分析多了很多動(dòng)作,而這里面的關(guān)鍵是“在shared pool 中是否有相同的sql”,而這就取決于是否使用綁定變量。
另:oracle9i引入了soft soft parse,先到pga中的session cursor cache list列表中去查找(session cursor cache list的長(zhǎng)度是由session_cache_cursor參數(shù)決定的),如果沒有找到這條sql,這時(shí)候才去檢查shard_pool. 對(duì)于Oltp系統(tǒng),很多時(shí)候硬分析的代價(jià)比執(zhí)行還要高,這個(gè)我們可以通過10046事件跟蹤得知。
(2)共享池中SQL語(yǔ)句數(shù)量太多,重用性極低,加速了SQL語(yǔ)句的老化,導(dǎo)致共享池碎片過多。
共享池中不同的SQL語(yǔ)句數(shù)量巨大,根據(jù)LRU原則,一些語(yǔ)句逐漸老化,最終被清理出共享池;這樣就導(dǎo)致shared_pool_size 里面命中率下降,共享池碎片增多,可用內(nèi)存空間不足。而為了維護(hù)共享池內(nèi)部結(jié)構(gòu),需要使用latch,一種內(nèi)部生命周期很短的lock,這將使用大量的cpu 資源,使得性能急劇下降。
不使用綁定變量違背了oracle 的shared pool 的設(shè)計(jì)的原則,違背了這個(gè)設(shè)計(jì)用來共享的思想。
2、怎么查看沒有使用綁定變量
select * from v$sql or v$sqlarea 查看是否有很多類似的語(yǔ)句,除了變量不一樣,其他的都一樣
3、如何使用綁定變量?
編寫java 程序時(shí),我們習(xí)慣都是定義JAVA 的程序變量,放入SQL 語(yǔ)句中,如
String v_id = 'xxxxx';
String v_sql = 'select name from table_a where id = ' + v_id ;
以上代碼,看起來是使用了變量v_id ,但這卻是java 的程序變量,而不是oracle 的綁定變量,語(yǔ)句傳遞到數(shù)據(jù)庫(kù)后,此java 的程序變量
已經(jīng)被替換成具體的常量值,變成:
select * from table_a where name = 'xxxxx' ;
假定這個(gè)語(yǔ)句第一次執(zhí)行,會(huì)進(jìn)行硬分析。后來,同一段java 代碼中v_id 值發(fā)現(xiàn)變化(v_id = 'yyyyyy'),數(shù)據(jù)庫(kù)又接收到這樣的語(yǔ)句:
select * from table_a where name = 'yyyyyy' ;
ORACLE 并不認(rèn)為以上兩條語(yǔ)句是相同的語(yǔ)句,因此對(duì)第二條語(yǔ)句會(huì)又做一次硬分析。這兩條語(yǔ)句的執(zhí)行計(jì)劃可是一樣的!
其實(shí),只需將以上java 代碼改成以下這樣,就使用了oracle 的綁定變量:
String v_id = 'xxxxx';
String v_sql = 'select name from table_a where id = ? '; //嵌入綁定變量
stmt = con.prepareStatement( v_sql );
stmt.setString(1, v_id ); //為綁定變量賦值
stmt.executeQuery();
在Java中,結(jié)合使用setXXX 系列方法,可以為不同數(shù)據(jù)類型的綁定變量進(jìn)行賦值,從而大大優(yōu)化了SQL 語(yǔ)句的性能。
4、java中應(yīng)用綁定變量的例子
PreparedStatement stmt = conn.prepareStatement('select a from b where c = ? ');
stmt.setLong(1,123);
stmt.executeQuery()
……
結(jié)論:
綁定變量主要適用在Oltp,運(yùn)行時(shí)間很短的系統(tǒng)。如客服系統(tǒng),時(shí)時(shí)地進(jìn)行insert方面的系統(tǒng)。 數(shù)據(jù)倉(cāng)庫(kù)系統(tǒng)不適用,和數(shù)據(jù)庫(kù)倉(cāng)庫(kù)系統(tǒng)的一條sql運(yùn)行時(shí)間相比,硬分析的代價(jià)顯然是微不足道的,通過硬分析去選擇正確的執(zhí)行計(jì)劃才是關(guān)鍵。
簡(jiǎn)單一句話,在Oltp系統(tǒng)中應(yīng)用綁定變量,性能會(huì)有質(zhì)的提高。
---引(http://www.apub.org/doc/2006/03/11/10/52/26/21883.html)