
Oracle SQL共享的机制(php).docx
5页Oracle SQL 共享的机制 --在 php 中使用绑定变量的方法在网站应用的研发中,一个较流行的方法便是使用 php 编程,php 编程方法简单明了,直接在html 中嵌入php 代码,对于研发基于数据库的动态应用十分方便不过,许多研发员在用php 研发基于 Oracle 数据库的应用时,仍沿习研发基于 Mysql 的应用的方法,未使用绑定变量,使得 Oracle SGA 区中 SQL 语句的重用性极低,浪费了内存,降低了系统性能因而,在此,先简单介绍一下 Oracle SQL 共享的机制,再介绍怎么在 php 中使用绑定变量,从而实现Oracle 数据库中 sql 语句的共享一、Oracle SQL 语句共享区的机制1、SGA 区结构:Oracle 数据库启动时,在内存中分配了一大片空间,为系统全局区(System Global Area),其中包含 Sql 共享池及数据缓存器(Data Buffer Cache)SGA 区的共享池部分主要由三个区域组成: 库缓存, 字典缓存, 控制结构库缓存包括共享 SQL 区,私有 SQL 区,PL/SQL 过程及包, 及控制结构,如锁及库缓存handles。
用户执行过的 Sql 语句存放于 Sql 共享池中,以便能重用,提高其效率2、SQL 语句在内存中的分布:Oracle 将其执行的每一条 SQL 语句存于共享 SQL 区及私有 SQL 区中当 Oracle 发现两个用户执行相同的 SQL 语句时,则为这些用户重用SQL 共享区不过,每一用户必须在私有SQL 区中拥有该语句的一份独立拷贝共享 SQL 区包含单一 SQL 语句或相同的 SQL 语句的解析树及执行计划通过为多个相同的 DML 语句使用一个共享 SQL 区,Oracle 节省了内存的使用, 特别是当许多用户使用同一应用时 共享SQL 区永远驻留在共享池中 www.bitsCN.com3、SQL 语句解析时进行的内存分配操作:当一个 SQL 语句被提交至 Oracle 去执行时,Oracle 自动地执行以下内存分配步骤:Oracle 检查共享池,看是否在共享 SQL 区中已存在相同的语句 若有,则该共享 SQL 区被用于执行该语句的新实例的后续操作 相应地,若在共享池中无该语句,则 Oracle 在共享池中分配一新的共享 SQL 区,其尺寸决定于该语句的复杂性 若一个 SQL 语句需求新的共享 SQL 区而整个共享池已被分配完毕, 则 Oracle 可通过一个最近最少修改机理从共享池中释放部分项目,直至可为新语句的共享 SQL 区提供足够的空间。
若 Oracle 释放了一个共享 SQL 区,则和该区相关联的 SQL 语句在下次重执行时,须重新解析并重新分配至另一共享 SQL 区 在两种情况下,用户专用 SQL 区和包含该语句的共享 SQL 区相关联因而,若能使语句得到共享,则其将减少内存的占用,同时,减少了 cpu 的占用,加快了语句执行的速度即使一个光标仍处于打开状态,若其非常久未被使用了,则其共享区也可能被从共享池中移出若该光标以后又被用于执行其语句,则 Oracle 重解析该语句并且在共享池中分配一新的共享 SQL 区4、私有 SQL 区私有 SQL 区包含绑定信息及运行时缓冲等数据 每一个提交一个 SQL 语句的会话均有一个私有 SQL 区每一提交相同 SQL 语句的用户有其使用单一共享 SQL 区的私有 SQL 区许多私有 SQL 区能和同一共享SQL 区相关联一个私有 SQL 区包括一个永久区和一个运行时区:一个永久区包含在执行过程中保持的绑定信息,数据类型转换的代码(在定义的数据类型和查询列的数据类型不一致时), 及其他状态信息(比如递归或远程光标数或并行查询的状态) 永久区的尺寸决定于绑定变量的数目及语句中指定的列数。
例如, 若一个查询中指定了非常多列,则永久区要大一些运行时区包含 SQL 语句被执行时使用的一些信息 运行时区的尺寸信赖于被执行的 SQL 语句的类型及其复杂性及被该语句处理的行的尺寸 一般而言, 用于 INSERT, UPDATE, 及 DELETE 的语句其运行区要比 SELECT 语句所需的运行区尺寸要小二、在 php 中不使用绑定变量和使用绑定变量的语法对比在 php 中,若不使用绑定变量,其对数据库的操作语法为:先解析已用变量值取代变量的语句,ora_parse(光标号,"包含变量的值的sql 语句"); 再执行语句ora_exec(光标号);使用绑定变量后,语法为先解析不含变量值的使用绑定变量的语句,再将 php 变量和 sql 中绑定变量相绑定,然后为为变量赋值,最后为执行语句如此,则尽管变量值可不断改动,但语句不会变化,从而可避免不必要的解析 中国网管联盟ora_parse(光标号,"包含未和变量对应的绑定变量的sql 语句");ora_bind(int 光标号, string PHP 变量名, string SQL 参数名, int 变量值长, int [变量类型] );语法中的 type 为可省略的参数选项,能设成下面三种数字之一:0 为内定值,表示输入/输出 (in/out);1表示输入 (in);2 表示输出 (out)。
然后,为为 php 变量进行赋值 最后,才为执行该语句 ora_exec(光标号);三、在 php 中不使用绑定变量和使用绑定变量的对比示例1、示例 1,在select 语句中使用绑定变量:语句:select sid, serial#, machine from v$session where username=’ 用户名’;假设执行三次,其参数值分别为 user1, user2, user3未使用绑定变量时,其语句为:ora_parse($list_cursor, "select sid, serial#, machine from v$session where username=$var_username"); ora_execute($list_cursor);内存中 SQL 共享区中便会存在以下三条语句:select sid, serial#, machine from v$session where username=’user1’;select sid, serial#, machine from v$session where username=’user2’; bbs.bitsCN.comselect sid, serial#, machine from v$session where username=’user3’;由于每次执行时,语句中的 var_username 值不同,从而语句便相应地不同,使得其无法共享。
使用绑定变量时,其语法为:先解析仅含绑定变量 p_1(p: parameter,参数),但无变量值的语句ora_parse($list_cursor, "select sid, serial#, machine from v$session where username=:p1"); 再将 php 程式变量 v_1 (v: Variable 变量)和 sql 语句中的绑定变量 p_1 相绑定, ora_bind($list_cursor,"v_1","p_1",strlen($var_username),1);在执行语句前,对该 php 程式变量进行赋值$v_1= $var_username; 然后,执行语句ora_exec($list_cursor);内存中 SQL 共享区中只会存在以下一条语句:select sid, serial#, machine from v$session where username=:p_1;而参数值 user1, user2, user3 则存放在执行该语句的用户会话的私有 sql 区此时,在系统 sql 共享区中,将该语句分两部分存储,一部分为前面仅含绑定变量的语句,为共享部分, 一部分为含有变量值的部分,为私有部分。
由于共享部分不含值,因而,对于不同用户不同参数值的查询, 其语句为一致的,从而实现了共享,避免了不必要的解析中国网管联盟2、示例 2,在 insert 语句中使用绑定变量: 语句:insert into test_table values(col1, col2); 假设执行三次,其参数值分别为 1,2; 2,3; 3,4 未使用绑定变量时,其语法为:ora_parse($list_cursor, "insert into test_table values($var_col1,$var_col2)"); ora_execute($list_cursor);内存中 SQL 共享区中便会存在以下三条语句:insert into test_table values(1,2); insert into test_table values(2,3); insert into test_table values(3,4);使用绑定变量后,其语句为:首先在原放变量的地方放入绑定变量,使其语句能共享, 解析语句ora_parse($list_cursor,"insert into test_table values(:p_col1,:p_col2)") or die; 将 php 变量和 sql 语句中的绑定变量相绑定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 变量进行赋值$v_col0 = $var_col1;$v_col1 = $var_col2; 执行语句ora_exec($list_cursor); bbs.bitsCN.com内存中 SQL 共享区中只会存在以下一条语句:insert into test_table values(:p_col1,:p_col2);而参数值则存放在执行该语句的用户会话的私有 sql 区, 从而由于共享部分为一致的,能在多用户中实现共享。
节约内存及 cpu 时间若为通过数组进行多组值的插入,则可将 ora_parse 及 ora_bind 置于循环开始之前,因为语句在循环中不会关闭,而且只是变量值变化,语句本身不变化,因而,只需一次解析及绑定而将 赋值语句及 ora_exec 语句置于循环中,由于减少了函数调用及网络传输的花费,更会大大提高速度四、在其他系统中使用绑定变量的方法:在 PowerBuilder 研发中,对于支持绑定变量的数据库系统,PowerBuilder 的绑定开关缺省参数为打开, 从而其在系统中参数位置为"?",实现了语句的共享若在连接数据库时,将DBParm 参数的 DisableBind 设为 1,则关闭绑定开关,不同参数值的同一语句无法共享在 Oracle Developer2000 研发的应用中,系统也为默认使用绑定变量不过,在二者中研发员自定义的代码,便需研发员自己使用绑定变量,否则也会由于未使用绑定变量而影响性能五、检查系统中 sql 语句共享程度及未使用绑定变量的语句的方法:bitsCN_com在 Oracle 8 及以上版本中,我们能通过查询视图 v$sysstat 获知系。
