♣答案部分

绑定变量这节的内容较多,下面给出这节涉及到的关系图:

(一)绑定变量的含义及优缺点

通常在高并发的OLTP系统中,可能会出现这样的现象,单个SQL的写法、执行计划、性能都是没问题的,但整个系统的性能就是很差,这表现在当系统并发的数量增加时,整个系统负载很高,CPU占用率接近100%。其实,这种系统性能随着并发量的递增而显著降低的现象,往往是因为这些系统没有使用绑定变量而产生了大量的硬解析所致。因为同一条SQL语句仅仅由于谓词部分变量的不同而在执行的时候就需要重新进行一次硬解析,造成SQL执行计划不能共享,这极大地耗费了系统时间和系统CPU资源。那么怎样才能降低OLTP应用系统的硬解析的数量呢?答案就是使用绑定变量。高并发的OLTP系统若没有使用绑定变量则会导致硬解析很大,这在AWR中的Load Profile部分可以很容易的看出来。

使用绑定变量能够有效降低系统硬解析的数量。对于同一类型的SQL语句若使用了绑定变量,则SQL文本就变得完全相同了,据此计算出来的哈希值也就完全相同,这就具备了可以重用解析树和执行计划的基础条件。这里的同一类型的SQL语句指的是除SQL文本中对应的输入值不同外其它部分都一模一样的SQL语句。例如,银行的查询余额的SQL语句,在成千上万次查询中都只是账户名不同,而SQL语句的其它部分都一样。若没有使用绑定变量,则每查询一次都必须进行一次硬解析。如果使用了绑定变量,假设每次可以节省0.001秒,那么在高并发下上千万次查询节省下来的时间将是非常大的,这在无形中就提高了系统的响应时间。

绑定变量(Bind Variable)其实质是变量,类似于经常使用的替代变量,只不过替代变量使用“&”作为占位符,而绑定变量使用英文冒号(:)作为占位符,替代变量使用方式为&VARIABLE_PARA,相应的绑定变量则为:BIND_VARIABLE_PARA。绑定变量通常出现在SQL文本中,用于替换WHERE或VALUES子句中的具体值。

绑定变量的优点如下所示:

①可以在库缓存(Library Cache)中共享游标,避免硬解析以及与之相关的额外开销。换句话说,绑定变量可以有效地减少SQL硬解析的次数,从而减少系统资源开销,这也是使用绑定变量最大的作用。

②在大批量数据操作时,可以大量减少闩锁的使用,从而避免闩锁(Latch)的争用。

③提高了代码的可读性(避免拼接式的硬编码)和安全性(防止SQL注入)。

绑定变量的缺点主要体现在当使用绑定变量时,查询优化器会忽略其具体值,因此,其预估的准确性远不如使用字面量值真实。当表的列上存在数据倾斜(表上的数据非均匀分布)时,Oracle可能会提供错误的执行计划,从而使得非高效的执行计划被使用。

需要注意的是,目标SQL中的绑定变量个数不宜太多,否则可能会导致目标SQL总的执行时间大幅度增长。增长的时间主要耗费在执行目标SQL时对每一个绑定变量都用其实际的值来替换(这个过程就是所谓的绑定变量值替换),目标SQL的SQL文本中的绑定变量的个数越多,这个替换过程所耗费的时间就越长,该SQL总的执行时间也就越长。

(二)绑定变量的适用场合

对于绑定变量应该根据系统的类型来决定是否使用绑定变量,如下所示:

l在高并发的OLTP系统中,SQL语句重复执行频度高,但处理的数据量较少,结果集也相对较小,尤其是使用表上的索引来缩小中间结果集,其解析时间通常会接近或高于执行时间,因此,在该场合一定要使用绑定变量,并且最好是使用批量绑定,因为可以有效降低系统硬解析的数量,这也是OLTP类型的系统在数据库端具备良好的性能和可扩展性的前提条件。

l在OLAP/DSS系统中,SQL语句执行次数相对较少,但返回的数据量较大,其SQL语句执行时间远高于其解析时间,硬解析对系统性能的影响是微乎其微的,因此,使用绑定变量对于总的执行时间影响不大,对系统性能的提升也非常有限。

l对于OLAP和OLTP混合型的应用系统,如果有循环,不管这个循环是在前台代码还是在后台PL/SQL代码中,循环内部的SQL语句一定要使用绑定变量,并且最好是使用批量绑定:至于循环外部的SQL语句,可以不使用绑定变量。

需要注意的是,对于实际的数据库对象,例如表、视图等,不能使用绑定变量替换,只能替换字面量。如果对象名是在运行时生成的,那么需要对其用字符串拼接,同时,SQL只会匹配已经在共享池中存在且相同的对象名。

(三)绑定变量的使用方法

1--① 在SQL中,用法如下所示:

2var v_empno number; --声明变量

3exec :v_empno :=7369; --变量赋值

4select * from scott.emp where empno=:v_empno;--使用绑定变量

5

6--② 在PL/SQL中,有如下几种用法:

7-----a.在静态SQL中使用绑定变量:

8DECLARE

9  V_NAME VARCHAR2(10);

10BEGIN

11  EXECUTE IMMEDIATE 'select ename from scott.emp where empno=:1' INTO V_NAME USING 7369;

12  DBMS_OUTPUT.PUT_LINE(V_NAME);

13END;

14-----b.在动态SQL中使用绑定变量:

15DROP TABLE T_EMP_LHR;

16CREATE TABLE T_EMP_LHR AS SELECT * FROM SCOTT.EMP;

17DECLARE

18  V_SQL1 VARCHAR2(4000);

19  V_SQL2 VARCHAR2(4000);

20    V_TMP1 NUMBER;

21    V_TMP2 NUMBER;

22BEGIN

23  V_SQL1:='INSERT INTO T_EMP_LHR(empno,ename,job) values(:1,:2,:3)';

24  EXECUTE IMMEDIATE V_SQL1 USING 6666,'lhr6','DBA';

25    V_TMP1:=SQL%ROWCOUNT;

26  V_SQL2:='INSERT INTO T_EMP_LHR(empno,ename,job) values(:1,:1,:1)';

27  EXECUTE IMMEDIATE V_SQL2 USING 6667,'lhr7','DBA';

28    V_TMP2:=SQL%ROWCOUNT;

29  DBMS_OUTPUT.PUT_LINE(V_TMP1+V_TMP2);

30END;

31

对于上述这种使用绑定变量的方式,关键字“USING”后传入的绑定变量具体输入值只与对应绑定变量在目标SQL中所处的位置有关,而与其名称无关,这意味着只要目标SQL中绑定变量所处的位置不同,它们所对应的绑定变量名称是可以相同的。上述代码执行结果为2,查询:

1LHR@orclasm > SELECT * FROM T_EMP_LHR t WHERE t.job='DBA';

2

3     EMPNO ENAME      JOB              MGR HIREDATE                   SAL       COMM     DEPTNO

4---------- ---------- --------- ---------- ------------------- ---------- ---------- ----------

5      6666 lhr6       DBA

6      6667 lhr7       DBA

7

8--再给出一个示例:

9DECLARE

10  V_COLUNMS VARCHAR2(30) :='EMPNO';

11  V_SQL VARCHAR2(4000);

12  V_ENAME VARCHAR2(20);

13BEGIN

14  V_SQL:='DELETE FROM T_EMP_LHR WHERE '||V_COLUNMS||'=:1 RETURNING ENAME INTO :2';

15  EXECUTE IMMEDIATE V_SQL USING 7369  RETURNING INTO  V_ENAME;

16  DBMS_OUTPUT.PUT_LINE(V_ENAME);

17END;

上述PL/SQL代码实现的是,删除表T_EMP_LHR里列EMPNO的值为7369的记录,并且将该记录的列ENAME的值打印出来。

c.在PL/SQL中通过批量绑定的方式使用绑定变量。

PL/SQL中的“批量绑定”是一种优化后的使用绑定变量的方式。批量绑定的优势在于它是一次处理一批数据,而不是像常规方式那样一次只处理一条数据,所以它能够有效减少PL/SQL引擎和SQL引擎上下文切换的次数。批量绑定的主要方式是使用BULK COLLECT INTO和FORALL的方式来实现,下面给出一个示例:

1DECLARE

2  TYPE EMPCURTYPE IS REF CURSOR; --定义游标类型及游标变量

3  EMP_CV EMPCURTYPE;

4  TYPE ENAME_TABLE_TYPE IS TABLE OF T_EMP_LHR.ENAME%TYPE INDEX BY BINARY_INTEGER; --定义结果集类型及变量

5  ENAME_TABLE ENAME_TABLE_TYPE;

6  SQL_STAT    VARCHAR2(120);

7  CN_BATCH_SIZE CONSTANT PLS_INTEGER := 1000;

8BEGIN

9  SQL_STAT := 'SELECT ENAME FROM T_EMP_LHR WHERE DEPTNO > :1'; --动态SQL字符串

10  OPEN EMP_CV FOR SQL_STAT  USING 1; --从动态SQL中打开游标

11  LOOP

12    FETCH EMP_CV BULK COLLECT INTO ENAME_TABLE LIMIT CN_BATCH_SIZE; --使用BULK COLLECT INTO提取结果集

13    FOR I IN 1 .. ENAME_TABLE.COUNT LOOP

14      DBMS_OUTPUT.PUT_LINE('Employee Name is ' || ENAME_TABLE(I));

15    END LOOP;

16    EXIT WHEN ENAME_TABLE.COUNT

17  END LOOP;

18  CLOSE EMP_CV;

19END;

其它示例可以参考【3.1.10.2如何使用批量动态SQL(FORALL及BULK子句的使用)?】。

③在Java中使用绑定变量

在Java中也有绑定变量和批量绑定的用法,本书不再详解。

真题1、下面有关SQL绑定变量的描述中,错误的是()

A、绑定变量是指在SQL语句中使用变量,改变变量的值来改变SQL语句的执行结果

B、使用绑定变量,可以减少SQL语句的解析,能减少数据库引擎消耗在SQL语句解析上的资源

C、使用绑定变量,提高了编程效率和可靠性,减少访问数据库的次数

D、使用绑定变量,查询优化器会预估的比字面变量更加真实

答案:D。

绑定变量是相对文本变量来讲的,所谓文本变量是指在SQL中直接书写查询条件,这样的SQL在不同条件下需要反复解析,绑定变量是指使用变量来代替直接书写条件,查询绑定变量在运行时传递,然后绑定执行。优点是减少硬解析,降低CPU的争用,节省SharedPool;缺点是不能使用固定的执行计划,SQL优化比较困难。

本题中,对于选项A,绑定变量就是之前不知道具体的值,只有运行的时候才知道值,改变变量的值来改变SQL语句的执行结果。所以,选项A错误。

对于选项B,使用绑定变量,可以减少SQL语句的解析,说法正确。所以,选项B错误。

对于选项C,使用绑定变量,减少解析次数,提高了编程效率和可靠性。所以,选项C错误。

对于选项D,使用绑定变量,查询优化器不知道具体的值,所以,其执行计划也不真实。所以,选项D正确。

所以,本题的答案为D。

本文选自《Oracle程序员面试笔试宝典》,作者:李华荣。

oracle 新建绑定变量,在Oracle中,绑定变量是什么?绑定变量有什么优缺点?相关推荐

  1. oracle新建数据库卡85,oracle数据库(新建数据库)超小白篇

    用过Mysql.sqlserver.Oracle 不知道有没有比oracle建库还复杂的 显示:win10系统 1.找到文件夹Oracle-OraDb10g_home1 2.选择Database Co ...

  2. centos 配置php开发环境变量配置,CentOS中配置PHP和Nginx环境变量

    搜索热词 一.摘要 在Linux CentOS系统上 安装完PHP和Nginx后,一般需要执行查看版本命令'PHP -v'和'Nginx -v',确认是否安装成功,如果在没有添加到环境变量之前,执行& ...

  3. php mysql 绑定变量,在MYSQL中,怎么用PDO绑定变量的方式插入数据?

    比如我的SQL语句是 INSERT INTO `man_db_write`.`man_articles` (`title`,`content`,`created`) VALUES (:0_title, ...

  4. oracle新建用户名和密码,Oracle安装后忘记用户名或密码+创建新登陆用户

    新安装Oracle 11g,不料没记住安装时的用户名和密码. 不用担心,打开sqlplus. 按如下步骤,新建一个登陆用户: 第一步:以sys登陆  sys/密码 as sysdba  此处的密码任意 ...

  5. oracle 新建TNS监听,oracle for windows 监听问题之TNS-12545

    操作系统版本:windows server 2012R2 数据库版本:oracle 11.2.0.1 问题描述:在一vmware虚拟机上搭建的windows server 2012R2,然后在wind ...

  6. java se环境变量_Windows 7中配置JDK(Java SE)环境变量

    系统:Windows 7旗舰版 JDK:Java SE 1.6 S1: 鼠标右键"计算机-属性-高级-环境变量-系统变量". S2: 在"系统变量"中,设置3项 ...

  7. php 函数内临时变量,在PHP中调用函数时使用临时变量

    我觉得你被这么多"浪费"深深震撼. 保持冷静,使用变量没什么不好,你应该经常使用它们.它们通常会使您的代码更具描述性,甚至更快. 这里的描述部分就是更具描述性的部分,如果你查看那一 ...

  8. java 静态变量 存储_Java中存储的静态方法和静态变量在哪里?

    静态方法(实际上所有方法)以及静态变量都存储在PermGen部分,因为它们是反射数据的一部分(类相关数据,而不是与实例相关的). 需要澄清的最新情况: 注意,只有变量及其技术值(原语或引用)存储在Pe ...

  9. c语言不用第三变量,C语言中几种不用第三变量交换两值的方法

    int main() { int a=3,b=4; int *p=(int *)malloc(sizeof(int)); *p=3; int *q=(int *)malloc(sizeof(int)) ...

  10. 成员函数在外部调用的方式总结-函数指针强制绑定+lamda函数闭包行为实现this指针的绑定

    C++函数指针 使用对象指针绑定进行调用 C++中因为函数指针需要绑定的对象才能使用,因此使用方法和C语言的函数指针不太一样 当然也可也借用该方法实现对私有函数的外部调用,因为只要使用对象强制取函数地 ...

最新文章

  1. 图像超分辨率与天气预报
  2. 【shell】创建长目录,目录存在则忽略,缺失则创建
  3. prefuse学习(二)显示一张图
  4. Javascript实现浏览器菜单命令
  5. 【WPF学习笔记】[转]周银辉之WPF中的动画 晓风影天之wpf动画——new PropertyPath属性链...
  6. IOS – OpenGL ES 调节图像灰色 GPUImageGrayscaleFilter
  7. [VB.NET]文件观察对象FileSystemWatcher
  8. 鸟哥的私房菜-基础篇学习-文件与目录管理-2-1
  9. 【数学建模】day05-微分方程建模
  10. C语言深度剖析-----数组基础
  11. java面试资料整理(高级必备)
  12. Vue — jTopo
  13. win10 安装 ssh后,命令行中仍无法运行ssh命令,‘ssh‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件
  14. RMAN传输表空间迁移数据
  15. 走近 Apple 中国研发团队。
  16. Null和Underfined
  17. 如何查找国内各大学本科学位论文?
  18. 桥接模式和装饰者模式的区别
  19. python画狗_Python 画一只单身狗作为情人节礼物
  20. 计算机二级60分容易吗,计算机二级哪个比较容易考

热门文章

  1. mqtt.fx连接mqtt的证书配置方法
  2. JSP—— JSTL
  3. 微信开放接口getUserInfo、login、getUserProfile的爱恨情仇?
  4. Android开发真机测试方法
  5. html5微课程制作,用H5做微课的好处,你知道多少?
  6. 【Spark】WordCount的多种实现方式
  7. 中小软件公司中,配置管理员的发展之路
  8. 【法律星球】人工智能在挑战知识产权法律规则
  9. java接口安全性解决方式
  10. 30 岁的程序员,我没有活成理想的模样,失败吗?