`
wutheringsea
  • 浏览: 262531 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Oracle读书摘录1---为什么要书写绑定变量的SQL语句

阅读更多

是否使用绑定变量这是导致Oracle性能问题的一个主要原因,也是阻碍可扩缩性的一个重要因素。

Oracle 将已解析、已编译的SQL 连同其他内容存储在共享池(shared pool)中,这是系统全局区(System

Global Area ,SGA)中一个非常重要的共享内存结构。这个结构能完成“平滑”操作,但有一个前提,要求开发人员

在大多数情况下都会使用绑定变量。如果你确实想让Oracle 缓慢地运行,甚至几近停顿,只要根本不使用绑定变量就

可以办到。

绑定变量(bind variable)是查询中的一个占位符。例如,要获取员工123 的相应记录,可以使用

以下查询:

select * from emp where empno = 123;

或者,也可以将绑定变量:empno 设置为123,并执行以下查询:

select * from emp where empno = :empno;

在典型的系统中,你可能只查询一次员工123,然后不再查询这个员工。之后,你可能会查询员工456,

然后是员工789,如此等等。如果在查询中使用直接量(常量),那么每个查询都将是一个全新的查询,在

数据库看来以前从未见过,必须对查询进行解析、限定(命名解析)、安全性检查、优化等。简单地讲,就

是你执行的每条不同的语句都要在执行时进行编译。

第二个查询使用了一个绑定变量:empno,变量值在查询执行时提供。这个查询只编译一次,随后会把

查询计划存储在一个共享池(库缓存)中,以便以后获取和重用这个查询计划。以上两个查询在性能和可

扩缩性方面有很大差别,甚至可以说有天壤之别。

从前面的描述应该能清楚地看到,与重用已解析的查询计划(称为软解析,soft parse)相比,解析

包含有硬编码变量的语句(称为硬解析,hard parse)需要的时间更长,而且要消耗更多的资源。硬解析

会减少系统能支持的用户数,但程度如何不太明显。这部分取决于多耗费了多少资源,但更重要的因素是

库缓存所用的闩定(latching)机制。硬解析一个查询时,数据库会更长时间地占用一种低级串行化设备,

这称为闩(latch),有关的详细内容请参见第6 章。这些闩能保护Oracle 共享内存中的数据结构不会同时

被两个进程修改(否则,Oracle 最后会得到遭到破坏的数据结构),而且如果有人正在修改数据结构,则

不允许另外的人再来读取。对这些数据结构加闩的时间越长、越频繁,排队等待闩的进程就越多,等待队

列也越长。你可能开始独占珍贵的资源。有时你的计算机显然利用不足,但是数据库中的所有应用都运行

得非常慢。造成这种现象的原因可能是有人占据着某种串行化设备,而其他等待串行化设备的人开始排队,

因此你无法全速运行。数据库中只要有一个应用表现不佳,就会严重地影响所有其他应用的性能。如果只有

一个小应用没有使用绑定变量,那么即使其他应用原本设计得很好,能适当地将已解析的SQL 放在共享池

中以备重用,但因为这个小应用的存在,过一段时间就会从共享池中删除已存储的SQL。这就使得这些设

计得当的应用也必须再次硬解析SQL。真是一粒老鼠屎就能毁了一锅汤。

如果使用绑定变量,无论是谁,只要提交引用同一对象的同一个查询,都会使用共享池中已编译的查

询计划。这样你的子例程只编译一次就可以反复使用。这样做效率很高,这也正是数据库期望你采用的做

法。你使用的资源会更少(软解析耗费的资源相当少),不仅如此,占用闩的时间也更短,而且不再那么频

繁地需要闩。这些都会改善应用的性能和可扩缩性。

要想知道使用绑定变量在性能方面会带来多大的差别,只需要运行一个非常小的测试来看看。在这个

测试中,将在一个表中插入一些记录行。我使用如下所示的一个简单的表:

ops$tkyte@ORA9IR2> drop table t;

Table dropped.

ops$tkyte@ORA9IR2> create table t ( x int );

Table created.

 

下面再创建两个非常简单的存储过程。它们都向这个表中插入数字1 到10 000;不过,第一个过程

使用了一条带绑定变量的SQL 语句:

ops$tkyte@ORA9IR2> create or replace procedure proc1

as

begin

for i in 1 .. 10000

loop

execute immediate

'insert into t values ( :x )' using i;

end loop;

end;

/

Procedure created.

 

第二个过程则分别为要插入的每一行构造一条独特的SQL 语句:

ops$tkyte@ORA9IR2> create or replace procedure proc2

as

begin

for i in 1 .. 10000

loop

execute immediate

'insert into t values ( '||i||')';

end loop;

end;

/

Procedure created

现在看来,二者之间惟一的差别,是一个过程使用了绑定变量,而另一个没有使用。它们都使用了动

态SQL(所谓动态SQL 是指直到运行时才确定的SQL),而且过程中的逻辑也是相同的。不同之处只在于是

否使用了绑定变量。

 

可以看到,如果使用了绑定变量(后面称为绑定变量方法),则只有4 次硬解析;没有使用绑定变量

时(后面称为无绑定变量方法),却有不下10 000 次的硬解析(每次插入都会带来一次硬解析)。还可以看

到,无绑定变量方法所用的闩数是绑定变量方法的两倍之多。这是因为,要想修改这个共享结构,Oracle

必须当心,一次只能让一个进程处理(如果两个进程或线程试图同时更新同一个内存中的数据结构,将非

常糟糕,可能会导致大量破坏)。因此,Oracle 采用了一种闩定(latching)机制来完成串行化访问,闩

(latch) 是一种轻量级锁定设备。不要被“轻量级”这个词蒙住了,作为一种串行化设备,闩一次只允

许一个进程短期地访问数据结构。闩往往被硬解析实现滥用,而遗憾的是,这正是闩最常见的用法之一。

共享池的闩和库缓存的闩就是不折不扣的闩;它们成为人们频繁争抢的目标。这说明,想要同时硬解析语

句的用户越多,性能问题就会变得越来越严重。人们执行的解析越多,对共享池的闩竞争就越厉害,队列

会排得越长,等待的时间也越久。

注意如果机器的处理器不止一个,在9i 和以上版本中,共享池还可以划分为多个子池,每个子池都

由其自己的闩保护。这样即使应用没有使用绑定变量,也可以提高可扩缩性,但是这并没有从根

本上克服闩定问题。

执行无绑定变量的SQL 语句,很像是在每个方法调用前都要编译子例程。假设把Java 源代码交付给

客户,在调用类中的方法之前,客户必须调用Java 编译器,编译这个类,再运行方法,然后丢掉字节码。

下一次想要执行同样的方法时,他们还要把这个过程再来一遍:先编译,再运行,然后丢掉字节码。你肯

定不希望在应用中这样做。数据库里也应该一样,绝对不要这样做。

对于这个特定的项目,可以把现有的代码改写为使用绑定变量,这是最好的做法。改写后的代码与原

先比起来,速度上有呈数量级的增长,而且系统能支持的并发用户数也增加了几倍。不过,在时间和精力

投入方面却要付出很大的代价。并不是说使用绑定变量有多难,也不是说使用绑定变量容易出错,而只是

因为开发人员最初没有使用绑定变量的意识,所以必须回过头去,几乎把所有代码都检查和修改一遍。如

果他们从第一天起就很清楚在应用中使用绑定变量至关重要,就不用费这么大的功夫了。

分享到:
评论

相关推荐

    oracle 数据库的绑定变量特性及应用

    为什么使用绑定变量? 绑定变量是解决 Oracle 应用程序可伸缩性的一个关键环节。如果不使用绑定变量,每次查询都是一个新的查询,这将导致 Oracle 需要分析、解析、安全检查、优化等一系列操作。这些操作将消耗大量...

    Oracle Sql语句转换成Mysql Sql语句

    本项目提供了一个Java源码工具,能够帮助用户便捷地将Oracle SQL语句转换为MySQL SQL语句。 Oracle SQL与MySQL SQL的主要差异在于以下几个方面: 1. **数据类型**:Oracle支持的数据类型如NUMBER、LONG、RAW等在...

    在Java中实现Oracle变量的绑定方法 .doc

    在Java中实现Oracle变量的绑定方法,主要是为了优化SQL语句的执行效率,减少数据库解析负担,提升系统性能。Oracle数据库在处理SQL语句时,会先进行解析,然后将解析后的SQL语句存储在共享池(Shared Pool)中。如果...

    浅谈oracle 数据库的绑定变量特性及应用

    - **性能优化**:绑定变量能够减少解析次数,因为数据库会将带有绑定变量的SQL语句视为同一语句,即使实际的变量值不同。这减少了解析和编译的时间,尤其是在频繁执行相同结构但不同值的SQL语句时。 - **内存使用...

    mysql虚拟了一个rowid(类似跟oracle的rowid)--SQL语句.sql

    mysql虚拟了一个rowid(类似跟oracle的rowid)--SQL语句

    sql绑定变量

    标题与描述中的“SQL绑定变量”这一知识点,主要聚焦于SQL语句中如何使用变量,尤其是在存储过程或函数中动态构建SQL语句时的关键技术。绑定变量允许在SQL语句中使用程序变量作为参数,这不仅提高了代码的可读性和...

    也谈oracle 数据库的绑定变量特性及应用

    1. 为什么使用绑定变量? - **提高性能**:使用绑定变量,Oracle只需解析和优化查询一次,然后将执行计划存储在共享池中。后续的查询可以重用这个执行计划,避免了重复的解析和优化过程,极大地提升了系统响应速度...

    动态SQL与绑定变量

    动态SQL与绑定变量是数据库编程中的重要概念,尤其在Oracle数据库中被广泛应用。动态SQL允许在运行时构建和执行SQL语句,而绑定变量则是在动态SQL中用于替代具体值的占位符,使得SQL语句更为灵活和高效。 ### 1. ...

    压测Oracle的SQL语句的性能情况

    2. **绑定变量**:使用绑定变量可以防止硬解析,提高SQL执行效率,减少解析开销。 3. **执行计划**:通过EXPLAIN PLAN分析SQL执行路径,了解数据库如何处理查询,找出可能导致性能问题的步骤。 4. **索引策略**:...

    Java中Oracle操作绑定变量使用用户工具模块解决方案

    为了提高SQL语句的执行效率,减少不必要的资源消耗,推荐使用绑定变量(即`PreparedStatement`)替代普通的`Statement`。这种方式可以显著减少数据库的解析成本,特别是在循环执行相同的SQL语句时,如批量更新数据等...

    oracle 查看当前会话执行的sql语句

    ### Oracle 查看当前会话执行的SQL语句 在Oracle数据库管理中,有时我们需要了解某个特定会话(Session)正在执行哪些SQL语句。这在性能调优、问题诊断等场景下尤为重要。以下将详细介绍如何通过不同的方法来查看...

    sqlserver自动生成sql语句工具sqlserver转oracle

    在压缩包子文件的文件名"ms转sql语句.exe"中,我们可以推测这可能是一个用于将SQL Server语句转换为Oracle兼容格式的可执行程序。这样的工具通常会提供用户友好的界面,让用户导入SQL Server的数据库元数据,然后...

    查找未使用绑定变量sql.sql

    查找未使用绑定变量sql.sql

    Oracle SQL语句性能优化

    Oracle SQL语句性能优化是数据库管理中的关键环节,直接影响到系统的响应速度和资源利用效率。本文将详细探讨优化Oracle SQL语句的几个核心策略。 1. 选择合适的优化器 Oracle 提供了三种优化器:RULE(基于规则)...

    Oracle Sql高效语句的写法诀窍

    如果查询包含绑定变量,Oracle就可以将SQL语句视为相同的,并允许共享相同的执行计划。 绑定变量的优点: 1. 性能提升:使用绑定变量能够显著减少SQL语句的解析次数,因为一旦SQL语句被解析后,相同语句的后续执行...

    上海交大网校Oracle作业二--写出SQL语句

    上海交大网校Oracle作业二--写出SQL语句

    ORACLE数据库SQL语句美化器

    对ORACLE-SQL进行一些布局优化,更新它的格式

    Oracle经典SQL语句

    ORACLE经典语句汇总 -- 字符串左填充和右填充,默认填充空格 -- 产生1~99行数据,少于一位则补0 -- 刪除相同行 -- 随机数 -- 产生业务流水号 -- 查询某张表中有哪些字段 -- 自循环表中 由叶子节点查父节点 -- 查子...

    oracle-instantclient-basic-11.1.0.1-1.x86_64.rpm

    oracle-instantclient-basic-11.1.0.1-1.x86_64.rpm

Global site tag (gtag.js) - Google Analytics