| 在php中使用綁定變量的方法(Oracle SQL共享的機制) 本文出自:http://www.computerworld.com.cn 作者: 趙華良 (2002-01-29 20:34:43) 在網(wǎng)站應用的開(kāi)發(fā)中,一個(gè)較流行的方法便是使用 php 編程,php編程方法簡(jiǎn)單明了,直接在html 中嵌入php 代碼,對于開(kāi)發(fā)基于數據庫的動(dòng)態(tài)應用十分方便。但是,許多開(kāi)發(fā)員在用php開(kāi)發(fā)基于Oracle 數據庫的應用時(shí),仍沿習開(kāi)發(fā)基于 Mysql 的應用的方法,未使用綁定變量,使得Oracle SGA 區中SQL語(yǔ)句的重用性極低,浪費了內存,降低了系統性能。 因而,在此,先簡(jiǎn)單介紹一下Oracle SQL共享的機制,再介紹如何在 php 中使用綁定變量,從而實(shí)現Oracle 數據庫中 sql語(yǔ)句的共享。
一、Oracle SQL語(yǔ)句共享區的機制 1、SGA 區結構: Oracle 數據庫啟動(dòng)時(shí),在內存中分配了一大片空間,為系統全局區(System Global Area),其中包含 Sql 共享池及數據緩存器(Data Buffer Cache)。SGA 區的共享池部分主要由三個(gè)區域組成: 庫緩存, 字典緩存, 控制結構。庫緩存包括共享 SQL 區,私有SQL區,PL/SQL 過(guò)程及包, 及控制結構,如鎖及庫緩存handles。用戶(hù)執行過(guò)的 Sql 語(yǔ)句存放于 Sql 共享池中,以便可以重用,提高其效率。
2、SQL語(yǔ)句在內存中的分布: Oracle 將其執行的每一條 SQL 語(yǔ)句存于共享SQL 區及私有 SQL 區中。當Oracle 發(fā)現兩個(gè)用戶(hù)執行相同的SQL語(yǔ)句時(shí),則為這些用戶(hù)重用SQL共享區。但是,每一用戶(hù)必須在私有SQL區中擁有該語(yǔ)句的一份獨立拷貝。共享SQL 區包含單一SQL語(yǔ)句或相同的SQL語(yǔ)句的解析樹(shù)及執行計劃。通過(guò)為多個(gè)相同的DML語(yǔ)句使用一個(gè)共享SQL區,Oracle 節省了內存的使用, 特別是當許多用戶(hù)使用同一應用時(shí)。 共享SQL區永遠駐留在共享池中。
3、SQL語(yǔ)句解析時(shí)進(jìn)行的內存分配操作: 當一個(gè)SQL語(yǔ)句被提交至Oracle 去執行時(shí),Oracle 自動(dòng)地執行以下內存分配步驟: Oracle 檢查共享池,看是否在共享SQL區中已存在相同的語(yǔ)句。 若有,則該共享SQL區被用于執行該語(yǔ)句的新實(shí)例的后續操作。 相應地,若在共享池中無(wú)該語(yǔ)句,則Oracle在共享池中分配一新的共享SQL區,其尺寸決定于該語(yǔ)句的復雜性。 若一個(gè)SQL語(yǔ)句要求新的共享SQL區而整個(gè)共享池已被分配完畢,則 Oracle 可通過(guò)一個(gè)最近最少修改機理從共享池中釋放部分項目,直至可為新語(yǔ)句的共享SQL區提供足夠的空間。 若 Oracle釋放了一個(gè)共享 SQL 區,則與該區相關(guān)聯(lián)的SQL語(yǔ)句在下次重執行時(shí),須重新解析并重新分配至另一共享SQL區。 在兩種情況下,用戶(hù)專(zhuān)用SQL區與包含該語(yǔ)句的共享SQL區相關(guān)聯(lián)。 因而,若能使語(yǔ)句得到共享,則其將減少內存的占用,同時(shí),減少了cpu 的占用,加快了語(yǔ)句執行的速度。 即使一個(gè)光標仍處于打開(kāi)狀態(tài),若其很久未被使用了,則其共享區也可能被從共享池中移出。若該光標以后又被用于執行其語(yǔ)句,則Oracle重解析該語(yǔ)句并且在共享池中分配一新的共享SQL區。
4、私有SQL區 私有SQL區包含綁定信息及運行時(shí)緩沖等數據。 每一個(gè)提交一個(gè)SQL語(yǔ)句的會(huì )話(huà)均有一個(gè)私有SQL區。 每一提交相同SQL語(yǔ)句的用戶(hù)有其使用單一共享SQL區的私有SQL區。許多私有SQL區可以與同一共享SQL區相關(guān)聯(lián) 一個(gè)私有SQL區包括一個(gè)永久區和一個(gè)運行時(shí)區: 一個(gè)永久區包含在執行過(guò)程中保持的綁定信息,數據類(lèi)型轉換的代碼(在定義的數據類(lèi)型與查詢(xún)列的數據類(lèi)型不一致時(shí)), 及其它狀態(tài)信息(比如遞歸或遠程光標數或并行查詢(xún)的狀態(tài))。 永久區的尺寸決定于綁定變量的數目及語(yǔ)句中指定的列數。 例如, 若一個(gè)查詢(xún)中指定了很多列,則永久區要大一些。 運行時(shí)區包含SQL語(yǔ)句被執行時(shí)使用的一些信息。 運行時(shí)區的尺寸信賴(lài)于被執行的SQL語(yǔ)句的類(lèi)型及其復雜性及被該語(yǔ)句處理的行的尺寸。 一般而言, 用于INSERT, UPDATE, 及 DELETE 的語(yǔ)句其運行區要比 SELECT 語(yǔ)句所需的運行區尺寸要小。
二、在 php 中不使用綁定變量與使用綁定變量的語(yǔ)法對比 在 php 中,若不使用綁定變量,其對數據庫的操作語(yǔ)法為:
先解析已用變量值取代變量的語(yǔ)句, ora_parse(光標號,"包含變量的值的sql語(yǔ)句"); 再執行語(yǔ)句 ora_exec(光標號);
使用綁定變量后,語(yǔ)法為先解析不含變量值的使用綁定變量的語(yǔ)句,再將php 變量與sql 中綁定變量相綁定,然后為為變量賦值,最后為執行語(yǔ)句。 如此,則盡管變量值可不斷改變,但語(yǔ)句不會(huì )變化,從而可避免不必要的解析。 ora_parse(光標號,"包含未與變量對應的綁定變量的sql語(yǔ)句"); ora_bind(int 光標號, string PHP 變量名, string SQL 參數名, int 變量值長(cháng), int [變量類(lèi)型] ); 語(yǔ)法中的 type 為可省略的參數選項,可以設成下面三種數字之一:0 為內定值,表示輸入/輸出 (in/out);1 表示輸入 (in);2 表示輸出 (out)。 然后,為為php變量進(jìn)行賦值。 最后,才為執行該語(yǔ)句。 ora_exec(光標號);
三、在 php 中不使用綁定變量與使用綁定變量的對比示例 1、示例1,在select 語(yǔ)句中使用綁定變量: 語(yǔ)句:select sid, serial#, machine from v$session where username=‘用戶(hù)名‘; 假設執行三次,其參數值分別為 user1, user2, user3
未使用綁定變量時(shí),其語(yǔ)句為: ora_parse($list_cursor, "select sid, serial#, machine from v$session where username=$var_username"); ora_execute($list_cursor);
內存中SQL共享區中便會(huì )存在以下三條語(yǔ)句: select sid, serial#, machine from v$session where username=‘user1‘; select sid, serial#, machine from v$session where username=‘user2‘; select sid, serial#, machine from v$session where username=‘user3‘; 由于每次執行時(shí),語(yǔ)句中的var_username 值不同,從而語(yǔ)句便相應地不同,使得其無(wú)法共享。
使用綁定變量時(shí),其語(yǔ)法為: 先解析僅含綁定變量 p_1(p: parameter,參數),但無(wú)變量值的語(yǔ)句 ora_parse($list_cursor, "select sid, serial#, machine from v$session where username=:p1"); 再將 php 程序變量 v_1 (v: Variable 變量)與 sql 語(yǔ)句中的綁定變量 p_1 相綁定, ora_bind($list_cursor,"v_1","p_1",strlen($var_username),1); 在執行語(yǔ)句前,對該php 程序變量進(jìn)行賦值 $v_1= $var_username; 然后,執行語(yǔ)句。 ora_exec($list_cursor);
內存中SQL共享區中只會(huì )存在以下一條語(yǔ)句: select sid, serial#, machine from v$session where username=:p_1; 而參數值user1, user2, user3 則存放在執行該語(yǔ)句的用戶(hù)會(huì )話(huà)的私有sql區
此時(shí),在系統 sql 共享區中,將該語(yǔ)句分兩部分存儲,一部分為前面僅含綁定變量的語(yǔ)句,為共享部分,一部分為含有變量值的部分,為私有部分。由于共享部分不含值,因而,對于不同用戶(hù)不同參數值的查詢(xún),其語(yǔ)句為一致的,從而實(shí)現了共享,避免了不必要的解析。
2、示例2,在insert 語(yǔ)句中使用綁定變量: 語(yǔ)句:insert into test_table values(col1, col2); 假設執行三次,其參數值分別為 1,2; 2,3; 3,4 未使用綁定變量時(shí),其語(yǔ)法為: ora_parse($list_cursor, "insert into test_table values($var_col1,$var_col2)"); ora_execute($list_cursor); 內存中SQL共享區中便會(huì )存在以下三條語(yǔ)句: insert into test_table values(1,2); insert into test_table values(2,3); insert into test_table values(3,4);
使用綁定變量后,其語(yǔ)句為: 首先在原放變量的地方放入綁定變量,使其語(yǔ)句可以共享, 解析語(yǔ)句 ora_parse($list_cursor,"insert into test_table values(:p_col1,:p_col2)") or die; 將 php變量與 sql 語(yǔ)句中的綁定變量相綁定 ora_bind($list_cursor,"v_col0","p_col1",strlen($var_col1),1); ora_bind($list_cursor,"v_col1","p_col2",strlen($var_col2),1); 為php 變量進(jìn)行賦值 $v_col0 = $var_col1; $v_col1 = $var_col2; 執行語(yǔ)句 ora_exec($list_cursor);
內存中SQL共享區中只會(huì )存在以下一條語(yǔ)句: insert into test_table values(:p_col1,:p_col2); 而參數值則存放在執行該語(yǔ)句的用戶(hù)會(huì )話(huà)的私有sql區, 從而由于共享部分為一致的,可以在多用戶(hù)中實(shí)現共享。節約內存及cpu 時(shí)間。
若為通過(guò)數組進(jìn)行多組值的插入,則可將 ora_parse 及ora_bind 置于循環(huán)開(kāi)始之前,因為語(yǔ)句在循環(huán)中不會(huì )關(guān)閉,而且只是變量值變化,語(yǔ)句本身不變化,因而,只需一次解析及綁定。而將 賦值語(yǔ)句及 ora_exec 語(yǔ)句置于循環(huán)中,由于減少了函數調用及網(wǎng)絡(luò )傳輸的花費,更會(huì )大大提高速度。
四、在其它系統中使用綁定變量的方法: 在 PowerBuilder 開(kāi)發(fā)中,對于支持綁定變量的數據庫系統,PowerBuilder 的綁定開(kāi)關(guān)缺省參數為打開(kāi),從而其在系統中參數位置為"?",實(shí)現了語(yǔ)句的共享。若在連接數據庫時(shí),將DBParm 參數的DisableBind設為1,則關(guān)閉綁定開(kāi)關(guān),不同參數值的同一語(yǔ)句無(wú)法共享。 在 Oracle Developer2000 開(kāi)發(fā)的應用中,系統也為默認使用綁定變量。但是,在二者中開(kāi)發(fā)員自定義的代碼,便需開(kāi)發(fā)員自己使用綁定變量,否則也會(huì )由于未使用綁定變量而影響性能。
五、檢查系統中sql語(yǔ)句共享程度及未使用綁定變量的語(yǔ)句的方法: 在 Oracle 8 及以上版本中,我們可以通過(guò)查詢(xún)視圖 v$sysstat 獲知系統中語(yǔ)句解析情況,從而了解綁定變量的使用情況。 select name , value from v$sysstat where name like ‘parse count%‘; 其會(huì )返回兩條記錄: parse count (hard) 為“硬”解析,即第一次執行sql 語(yǔ)句時(shí)進(jìn)行的解析,parse count (total) 為所有解析次數,其由hard 與 soft 兩部分之和組成,soft 解析為當語(yǔ)句在共享池中找到時(shí),進(jìn)行的權限檢查操作,其速度比 hard parse 要快得多。因而,若發(fā)現 hard parse 占total 的比率較高,則表示語(yǔ)句未得到很好的共享,系統性能將受到影響。 此時(shí),可通過(guò)檢查 v$sqlarea 視圖或 v$sqltext 視圖中所有sql語(yǔ)句的內容確定哪些語(yǔ)句未使用綁定變量,并由開(kāi)發(fā)員相應進(jìn)行修改。
從 v$sqlarea 查看 sql 語(yǔ)句的方法為, select SQL_TEXT, EXECUTIONS , PARSE_CALLS from v$sqlarea where 限制條件; 其只能查看 sql 語(yǔ)句的前1000個(gè)字節。若有超過(guò)1000字節的sql語(yǔ)句,則應通過(guò)v$sqltext 視圖查看。
select sql_text, piece, hash_value from v$sqltext where 限制條件 order by hash_value, piece; 其為按每行64字節分布,piece為行號。 為了不影響性能,一般為先將某一時(shí)間點(diǎn)的 v$sqlarea 的內容復制到一個(gè)臨時(shí)表中,再對該表中記錄進(jìn)行分析。 在 Oracle 7 中,只能從 v$sysstat 中查出所有的解析計數,但仍可從 v$sqlarea 及 v$sqltext 中查出未使用綁定變量的語(yǔ)句并進(jìn)行修改。 (http://www.fanqiang.com) 進(jìn)入【UNIX論壇】 |
聯(lián)系客服