Oracle-绑定变量binding variable解读
文章目錄
- 綁定變量概述
- 綁定變量詳解
- 綁定變量使用限制條件
- 字符級的比較
- 兩個語句所指的對象必須完全相同
- 兩個SQL語句中必須使用相同的名字的綁定變量(bind variables)
- 查詢使用綁定變量可以受益的SQL
- 綁定變量栗子
- 在Java中的使用綁定變量
- 實際工作中的應(yīng)用
- 總結(jié)
綁定變量概述
Oracle 中,對于一個提交的sql語句,存在兩種可選的解析過程, 一種叫做硬解析,一種叫做軟解析.
一個硬解析需要經(jīng)解析,制定執(zhí)行路徑,優(yōu)化訪問計劃等許多的步驟.
硬解析不僅僅耗費大量的cpu,更重要的是會占據(jù)重要的門閂(latch)資源,嚴重的影響系統(tǒng)的規(guī)模的擴大(即限制了系統(tǒng)的并發(fā)行), 而且引起的問題不能通過增加內(nèi)存條和cpu的數(shù)量來解決。
之所以這樣是因為latch是為了順序訪問以及修改一些內(nèi)存區(qū)域而設(shè)置的,這些內(nèi)存區(qū)域是不能被同時修改。
引申一下 latch:
Latch是用于保護SGA區(qū)中共享數(shù)據(jù)結(jié)構(gòu)的一種串行化鎖定機制。
Latch就像是內(nèi)存上的鎖,可以由一個進程非??焖俚丶せ詈歪尫?#xff0c;用于防止對一個共享內(nèi)存結(jié)構(gòu)進行并行訪問。
如果latch不可用,那么將記錄latch釋放失敗。
絕大多數(shù)latch問題都與沒有使用綁定變量(library-cache latch(庫緩存latch))、重做日志生成問題(redo-allocation latch(重做日志的分配latch ))、緩存競爭問題(cache-buffers LRU-chain latch(緩存的最近最少使用鏈latch))及緩存中的熱塊(cache-buffers chain latch(緩存鏈latch))有關(guān)。
當一個SQL語句提交后,Oracle 在接收到這些SQL后,會先對這個SQL做一個hash 函數(shù)運算,得到一個Hash值,然后到共享池中尋找是否有和這個hash 值匹配的SQL存在。 如果找到了,Oracle將直接使用已經(jīng)存在的SQL 的執(zhí)行計劃去執(zhí)行當前的SQL,然后將結(jié)果返回給用戶。 如果在共享池中沒有找到相同Hash 值的SQL,oracle 會認為這是一條新的SQL, 會進行硬解析。
而唯一使得oracle 能夠重復(fù)利用執(zhí)行計劃的方法就是采用綁定變量。
綁定變量的本質(zhì)就是本來需要做Oracle 硬解析的SQL 變成軟解析,以減少ORACLE 花費在SQL解析上的時間和資源。
綁定變量只是起到占位的作用,同名的綁定變量并不意味著在它們是同樣的,在傳遞時要考慮的是傳遞的值與綁定變量出現(xiàn)順序的對位,而不是綁定變量的名稱。
簡單的說,綁定變量就是拿一個變量來代替謂詞常量,讓Oracle每次對用戶發(fā)來的SQL做hash 運算時,運算出的結(jié)果都是同樣的Hash值,于是將所有的用戶發(fā)來的SQL看作是同一個SQL來對象。
綁定變量是在通常情況下能提升效率,非正常的情況如下:
在字段(包括字段集)建有索引,且字段(集)的集的勢非常大(也就是有個值在字段中出現(xiàn)的比例特別的大)的情況下,使用綁定變量可能會導(dǎo)致查詢計劃錯誤,因而會使查詢效率非常低。這種情況最好不要使用綁定變量。
但是并不是任何情況下都需要使用綁定變量,下面是兩種例外情況:
- 1.對于隔相當一段時間才執(zhí)行一次的SQL語句,這是利用綁定變量的好處會被不能有效利用優(yōu)化器而抵消
- 2.數(shù)據(jù)倉庫的情況下。
綁定變量不能當作嵌入的字符串來使用,只能當作語句中的變量來用。不能用綁定變量來代替表名、過程名、字段名等.
從效率來看,由于oracle10G放棄了RBO,全面引入CBO,因此,在10G中使用綁定變量效率的提升比9i中更為明顯。
綁定變量詳解
綁定變量使用限制條件
為了不重復(fù)解析相同的SQL語句,在第一次解析之后, ORACLE將SQL語句存放在內(nèi)存中.這塊位于系統(tǒng)全局區(qū)域SGA(system global area)的共享池(shared buffer pool)中的內(nèi)存可以被所有的數(shù)據(jù)庫用戶共享.
因此,當你執(zhí)行一個SQL語句時,如果它和之前的執(zhí)行過的語句完全相同, ORACLE就能很快獲得已經(jīng)被解析的語句以及最好的執(zhí)行路徑. ORACLE的這個功能大大地提高了SQL的執(zhí)行性能并節(jié)省了內(nèi)存的使用。
數(shù)據(jù)庫管理員必須在init.ora中為這個區(qū)域設(shè)置合適的參數(shù),當這個內(nèi)存區(qū)域越大,就可以保留更多的語句,當然被共享的可能性也就越大了.
當你向ORACLE 提交一個SQL語句,ORACLE會首先在這塊內(nèi)存中查找相同的語句.這里需要注明的是,ORACLE對兩者采取的是一種嚴格匹配,要達成共享,SQL語句必須完全相同(包括空格,換行等).
共享的語句必須滿足三個條件:
字符級的比較
當前被執(zhí)行的語句和共享池中的語句必須完全相同.
例如:
和下列每一個都不同
SELECT * from EMP;Select * From Emp;SELECT * FROM EMP;兩個語句所指的對象必須完全相同
兩個SQL語句中必須使用相同的名字的綁定變量(bind variables)
比如:
第一組的兩個SQL語句是相同的(可以共享),而第二組中的兩個語句是不同的(即使在運行時,賦于不同的綁定變量相同的值)
a.
b.
select pin , name from people where pin = :blk1.ot_ind;select pin , name from people where pin = :blk1.ov_ind;查詢使用綁定變量可以受益的SQL
在V$SQL視圖中有個 FORCE_MATCHING_SIGNATURE字段,可以識別使用綁定變量可能會獲益的SQL,如果SQL已經(jīng)使用綁定變量 ,則 FORCE_MATCHING_SIGNATURE對其進行標識時,將給出同樣的簽名。
也就是說,如果有兩條或兩條以上的SQL語句,除了字面量之外,其他的都是相同的,則它們將擁有相同的 FORCE_MATCHING_SIGNATURE值。使用這個特性,下面,我給出一條SQL,用來查詢可以使用綁定變量進行獲益的SQL語句
with match_infoas(select force_matching_signature,count(*) matches,max(sql_id || child_number) max_sql_child,dense_rank() over(order by count(*) desc) rkfrom v$sqlwhere force_matching_signature <> 0and parsing_schema_name <> 'SYS'group by force_matching_signaturehaving count(*) > 5)select sql_id, matches, parsing_schema_name schema, sql_textfrom v$sqljoin match_infoon (sql_id || child_number) = max_sql_child/* where rk <= 5*/order by matches desc;綁定變量栗子
http://blog.csdn.net/yangshangwei/article/details/53310802#t14
在Java中的使用綁定變量
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ù)類型的綁定變量進行賦值,從而大大優(yōu)化了SQL 語句的性能。
實際工作中的應(yīng)用
// 此處需要增加 工單ID 查詢條件if(MapUtils.getString(paramMap, "workorderId")!=null && !MapUtils.getString(paramMap, "workorderId").equals("")){// 1,不使用綁定變量,寫死的情況qryStr.append(" AND WO.WORKORDER_ID=").append(MapUtils.getString(paramMap, "workorderId"));// 2,使用綁定變量的寫法/**whereStr的寫法,表示使用paramMap里面的workorderId去set這個綁定變量* whereStr最后的逗號可以不切割,集成的方法中會做統(tǒng)一處理* qryStr和whereStr必須相輔相成,一個 ? 號一個變量。*/qryStr.append(" AND WO.WORKORDER_ID=?");whereStr.append("workorderId,");}總結(jié)
合理使用綁定變量后,執(zhí)行的時間將得到了顯著的提高,同時緩沖區(qū)的命中率得了數(shù)量級的提升,等待事件將得到了減少。
總結(jié)
以上是生活随笔為你收集整理的Oracle-绑定变量binding variable解读的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle-数据字典解读
- 下一篇: ORACLE-WITH 子句详解