Oracle绑定变量分级-实测

在oracle 中,对于一个提交的sql语句,存在两种可选的解析过程, 一种叫做硬解析,一种叫做软解析.

一个硬解析需要经解析,制定执行路径,优化访问计划等许多的步骤.硬解释不仅仅耗费大量的cpu,更重要的是会占据重要的们闩(latch)资源,严重的影响系统的规模的扩大(即限制了系统的并发行), 而且引起的问题不能通过增加内存条和cpu的数量来解决。这是因为门闩是为了顺序访问以及修改一些内存区域而设置的,这些内存区域是不能被同时修改。当一个sql语句提交后,oracle会首先检查一下共享缓冲池(shared pool)里有没有与之完全相同的语句,如果有的话只须执行软分析即可,否则就得进行硬分析。

而唯一使得oracle 能够重复利用执行计划的方法就是采用绑定变量。绑定变量的实质就是用于替代sql语句中的常量的替代变量。绑定变量能够使得每次提交的sql语句都完全一样。

普通sql语句:

update ipsdba_test set sn1=‘SN11’,sn2=‘SN12’,sn3=‘SN13’ where sn_key=1;

update ipsdba_test set sn1=‘SN21’,sn2=‘SN22’,sn3=‘SN23’ where sn_key=1;

update ipsdba_test set sn1=‘SN31’,sn2=‘SN32’,sn3=‘SN33’ where sn_key=1;

含绑定变量的sql 语句:

update ipsdba_test set sn1=:1,sn2=:2,sn3=:3 where sn_key=1;

绑定变量是我们目前开发系统应用中广泛使用的数据库SQL语言技术。大多数情况下,我们借助绑定变量可以在library cache中共享游标,因此可以有效的提高shared cursor使用的效率,可以减少硬解析以及相关的额外开销。

但是,凡事有利必有弊,使用绑定变量在一定情况下也会带来问题,一个就是“大名鼎鼎”的bind peeking,另一个就是bind graduation.

Bind peeking因其在执行“Bad”SQL时,存在强制共享非最优执行计划的可能被广泛关注,相关文章比较多,本文不讨论。而bind graduation无论在网络还是MOS中,都是较少涉及的话题。本篇就介绍Oracle bind graduation相关细节。

1、 Bind Graduation简介

Bind Graduation技术主要是针对字符串绑定变量的一种SQL共享技术。在我们使用SQL绑定变量时,除了字面SQL和其他一些环境变量因素会影响到SQL子游标共享外,使用绑定变量的长度也是会影响到SQL cursor sharing的。

oracle服务器端对于绑定变量,根据变量长度进行了分级,对于VARCHAR2类型共有如下4级:
第一级: 1-32(GB2312/GBK:1-16,UTF8:1-10;下面类推)
第二级: 33-128
第三级: 129-2000
第四级: 2000+

注意:这个长度是字节数,经jdbc环境测试,和rdbms字符集关系密切,GB2312字符集下每个字符占两个字节,UTF8字符集下每个字符三个字节;无论汉字/英文

Bind Graduation技术的推出,初衷还是为了加强共享游标的可用性和一定程度上提高执行计划最优性。实际情况是如何呢?我们下面分别进行试验验证。

2、测试环境准备

2.1 oracle rdbms环境
在这里插入图片描述

2.3 java环境:jdk1.6,jdbc:oracle 11g客户端自带的ojdbc6.jar

2.4 建表&数据

create table ipsdba_test(sn_key number,sn1 varchar2(30),sn2 varchar2(40),sn3 varchar2(256));

insert into ipsdba_test values(1,‘SN11’,‘SN12’,‘SN13’);

insert into ipsdba_test values(2,‘SN21’,‘SN22’,‘SN23’);

insert into ipsdba_test values(3,‘SN31’,‘SN32’,‘SN33’);

2.5 编写测试java脚本

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
 
public class jdbctest {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
    Class.forName("oracle.jdbc.driver.OracleDriver");
    Connection conn=DriverManager.getConnection("jdbc:oracle:thin:@//192.168.1.67:1522/ipsbak","xlzhu","xlzhu");//?useUnicode=true&characterEncoding=utf-8
    PreparedStatement ps=null;
	try {
		String sql="update ipsdba_test set sn1=?,sn2=?,sn3=? where sn_key=1";
		String v_sn1="SN01";//30
		String v_sn2="2";//40
		String v_sn3="";//256;   31:SN12345678923456789012345678901
		ps=conn.prepareStatement(sql);      
		ps.setString(1,v_sn1);
		ps.setString(2,v_sn2);
		ps.setString(3,v_sn3);
		
		int ret=ps.executeUpdate();
		System.out.println("update ok");
	} catch (Exception e) {
		System.out.println("error..."+e.getMessage());
	}
	finally {
		if(ps!=null)
			ps.close();
		if(conn!=null)
			conn.close();
	}
	
    }
}

3、测试过程

3.1 运行java程序&查询数据库
在这里插入图片描述
在这里插入图片描述
3.2修改java源码中变量v_sn2=“SN12345678123456”,共16位字符,运行java程序&查询数据库
在这里插入图片描述
在这里插入图片描述
3.3修改java源码中变量v_sn2=“SN123456781234567”,共17位字符,运行java程序&查询数据库

在这里插入图片描述
在这里插入图片描述

3.4 修改数据类型测试,运行java程序&查询数据库
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4、总结

上面的实验,告诉了我们bind graduation的几个特性:

1、0-32、32-128分别为两个bind分区,不同分区的绑定变量声明值不共享游标;

2、绑定变量的不同类型也不共享游标

在MOS[ID 258742.1]中,找到一段关于graduation的只言片语描述:

Depending on the length used, the character binds in the child cursor can all be created using the same bind length;

skipping bind graduation and keeping the child chain relatively small.

This helps to alleviate a potential cursor-sharing problem related to graduated binds.

The level of the event is the bind length to use, in bytes.

从上面的描述中,我们可以看到graduation的技术初衷还是为了缓解(而不是解决)绑定变量带来的游标共享问题。

对执行计划而言,Oracle是需要单独分配内存空间给执行计划进行保存的。如果其中有使用绑定变量,Oracle是会将绑定变量保存在child cursor中的。在分配varchar2类型的绑定变量大小空间时,使用bind graduation可以分配略小的适当空间。

一般情况下,实现graduation的分区数量是有限的。也就是说,即使多次生成child cursor,带来version count过多的风险也是有限的。

如果遇到很极端的情况,比如项目组希望实现绝对的共享或者说变量数目较多引起version count过多,可以使用10503事件控制bind graduation的出现,或者直接在代码中声明varchar2(2000)的绑定变量即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值