日期:2014-05-16  浏览次数:20458 次

Troubleshooting Oracle Performance 翻译

?

(http://bing.proxysec.com/baidu.com.php?u=b228d2e9a31add4Oi8vd3d3LmRiYW5vdGVzLm5ldC9kYXRhYmFzZS90b3BfYmluZF92YXJpYWJsZXMuaHRtbA%3D%3D&b=1)

绑定变量

绑定变量通过两种方式来影响应用。第一,从开发的角度看,它使得开发或者变得简单,或者是变得更加困难(或更精确地讲,需要更多或更少地编码)。既然这样,具体的效果就取决于用来执行SQL语句的应用程序接口(Application Programming Interface, API)。例如,如果是使用PL/SQL来编码,使用绑定变量来执行就会更加简单。另一方面,如果是使用JDBC(Java Data Base Connectivity)来开发,不使用绑定变量来执行SQL语句则会更加简单。第二,从性能的角度看,绑定变量既有优势也有劣势。

注意:你将会在下面的内容中看到一些执行计划。第6章将会介绍如何获取并解释执行计划。如果有什么不清楚的话,可以考虑稍后返回本章。

2.5.1 优势

绑定变量的优势是可以在库缓存中共享游标,这样就可以避免硬解析以及与之相关的额外开销。下面内容是运行脚本bind_variables.sql的结果,它展示了三个INSERT语句由于使用绑定变量而共享了库缓存中的同一个游标的情形。

SQL代码, 略.

可是,也有一些情况下,即使使用绑定变量也会产生多个子游标。下面的例子就展示了这种情况。注意,INSERT语句与前面例子中的完全一样。只有对应的VARCHAR2变量的最大长度发生了变化(从32变成33了)。

SQL代码, 略.

之所以会创建新的子游标(子游标1),是因为相对于最初的3个INSERT语句来讲,第4个INSERT语句的执行环境发生了变化。 这个不匹配可以通过查询视图 v$sql_shared_cursor 来得到确认,是绑定变量的原因。

SQL代码, 略.

这是由于数据库引擎应用了绑定变量分级(graduation)。这个功能的目的是为了最小化子游标的数量,它是根据绑定变量的长短将绑定变量(各个大小不同)分为四个级别。在32个字节以内被分在第一个级别,33到128个字节的被分在第二个级别,129到2000个字节的被分在第三个级别,其余的大于2000个字节的被分在第四个级别。NUMBER类型的绑定变量被分在它的最大长度22个字节上的级别上。从下面的例子可以看到,视图v$sql_bind_metadata显示了级别的最大长度。注意,即使在子游标1的变量长度只有33的时候,也是使用最大长度为128的级别。

SQL代码, 略.

系统不要求每次生成子游标的时候都生成一个新的执行计划。新的执行计划是否与另一个子游标使用的执行计划一致,也依赖于绑定变量的值。这将在下面的内容中进行介绍。

2.5.2 劣势

在WHERE从句中使用绑定变量的缺点是会有一些至关重要的信息对查询优化器不可见。事实上,对查询优化器来讲,使用直接文本要比使用绑定变量来的更好。使用直接文本可以提高成本估算的准确性。当检查一个值是否在可用数值范围以外(也就是,小于存储在这个字段的最小值,或者大于最大值)或者是否利用到直方图(histogram)时,就更是这样了。为了展示的需要,我们准备了一个含有1000条记录的表,它的字段id的值在1(最小值)到1000(最大值)之间。

SQL代码, 略.

如果一个用户查询id小于990的所有记录,查询优化器知道(根据对象的统计信息)有差不多99%的记录被筛选。因此,它会选择使用基于全表扫描的执行计划。同时请注意,估算出的基数(执行计划中Rows字段的信息)与查询语句实际返回的记录数是否相符。

SQL代码, 略.

当另外一个用户查询id小于10的所有记录时,查询优化器知道只有大约1%的记录会被选中。因此,它会选择使用基于索引扫描的执行计划。在这个例子中,也请注意估算的准确与否。

SQL代码, 略.