Oracle绑定变量分级(Bind Graduation)

Oracle绑定变量分级(Bind Graduation)



绑定变量分级(Bind Graduation)是指Oracle在PL/SQL代码中会根据文本型绑定变量的定义长度而将这些文本型绑定变量分为四个等级,如下所示:

l 定义长度小于等于32字节(Byte)的文本型绑定变量被分在第一个等级,Oracle为其分配32字节的内存空间。

l 定义长度在[33,128]字节之间的被分在第二个等级,Oracle为其分配128字节的内存空间。

l 定义长度在[129,2000]字节之间的文本型绑定变量被分在第三个等级,Oracle为其分配2000字节的内存空间。

l 定义长度在2000字节以上被分在第四个等级,Oracle为此等级的文本型绑定变量分配的内存空间大小取决于对应文本型绑定变量所传入的实际绑定变量值的大小。如果实际传入的绑定变量值小于或等于2000字节,那么Oracle会为其分配2000字节的内存空间。如果实际传入的绑定变量值大于2000字节,那么Oracle会为其分配4000字节的内存空间。

需要注意的是,绑定变量分级仅适用于文本型的绑定变量,Oracle不会对数值(NUMBER)型的绑定变量做绑定变量分级。Oracle数据库中数值型的变量最大只能占用22字节,所以对于数值型的绑定变量而言,Oracle统一为其分配了22字节的内存空间。

如果在PL/SQL代码中使用了文本型绑定变量,只要其SQL文本中文本型绑定变量的定义长度发生了变化,那么Oracle为这些绑定变量所分配的内存空间的大小也可能会随之发生变化,而一旦Oracle为这些绑定变量所分配的内存空间的大小发生了变化,那么该SQL之前存储在Child Cursor中的解析树和执行计划就不能被重用了。其原因是Child Cursor中除了会存储目标SQL的解析树和执行计划之外,还会存储该SQL所使用的绑定变量的类型和长度,这意味着即使该SQL的SQL文本没有发生任何改变,只要其SQL文本中文本型绑定变量的定义长度发生了变化,那么该SQL再次执行时就可能还是做硬解析(新生成一个子游标)。

下面给出一个示例(数据库版本为11.2.0.3):

建表T_BG_20170610_LHR,并给出5个PL/SQL代码:

CREATE TABLE T_BG_20170610_LHR(N NUMBER(10),V VARCHAR2(3000));

--SQL_TEXT1:硬解析

DECLARE

  N NUMBER(10) :=1;--分配22字节的内存空间

  V VARCHAR2(32) :='XIAOMAIMIAO1';--分配32字节的内存空间

BEGIN

  EXECUTE IMMEDIATE 'INSERT INTO T_BG_20170610_LHR VALUES(:N,:V)' USING N, V;

  COMMIT;

END;

/

--SQL_TEXT2:硬解析

DECLARE

  N NUMBER(10) :=2;--分配22字节的内存空间

  V VARCHAR2(33) :='XIAOMAIMIAO2';--分配128字节的内存空间

BEGIN

  EXECUTE IMMEDIATE 'INSERT INTO T_BG_20170610_LHR VALUES(:N,:V)' USING N, V;

  COMMIT;

END;

/

 

--SQL_TEXT3:硬解析

DECLARE

  N NUMBER(10) :=3;--分配22字节的内存空间

  V VARCHAR2(129) :='XIAOMAIMIAO3';--分配2000字节的内存空间

BEGIN

  EXECUTE IMMEDIATE 'INSERT INTO T_BG_20170610_LHR VALUES(:N,:V)' USING N, V;

  COMMIT;

END;

/

 

--SQL_TEXT4:软解析

DECLARE

  N NUMBER(10) :=4;--分配22字节的内存空间

  V VARCHAR2(2001) :='XIAOMAIMIAO4';--分配2000字节的内存空间

BEGIN

  EXECUTE IMMEDIATE 'INSERT INTO T_BG_20170610_LHR VALUES(:N,:V)' USING N, V;

  COMMIT;

END;

/

--SQL_TEXT5:软解析

DECLARE

  N NUMBER(10) :=5;--分配22字节的内存空间

  V VARCHAR2(32767) :='XIAOMAIMIAO5';--分配2000字节的内存空间

BEGIN

  EXECUTE IMMEDIATE 'INSERT INTO T_BG_20170610_LHR VALUES(:N,:V)' USING N, V;

  COMMIT;

END;

/

--SQL_TEXT6: 硬解析

DECLARE

  N NUMBER(10) :=6;  --分配22字节的内存空间

  V VARCHAR2(32767) :=RPAD('XIAOMAIMIAO6',2002,'8');  --字符串长度为2002,分配4000字节的内存空间

BEGIN

  EXECUTE IMMEDIATE 'INSERT INTO T_BG_20170610_LHR VALUES(:N,:V)' USING N, V;

  COMMIT;

END;

/

执行上述建表语句和PL/SQL代码,查看结果:

LHR@orclasm > col v format a13

LHR@orclasm > select * from T_BG_20170610_LHR T WHERE T.N<=5;

 

         N V

---------- -------------

         1 XIAOMAIMIAO1

         2 XIAOMAIMIAO2

         3 XIAOMAIMIAO3

         4 XIAOMAIMIAO4

         5 XIAOMAIMIAO5

LHR@orclasm > SELECT T.N,LENGTH(T.V) FROM T_BG_20170610_LHR T;

 

         N LENGTH(T.V)

---------- -----------

         1          12

         2          12

         3          12

         4          12

         5          12

         6        2002

一旦Oracle为这些文本型绑定变量所分配的内存空间的大小发生了变化,那么该SQL之前存储在Child Cursor中的解析树和执行计划就不能被重用了。所以这里Oracle在执行范例PL/SQL代码1、2、3时每次都是硬解析,但在执行范例PL/SQL代码4和5时会用软解析/软软解析,因为范例PL/SQL代码4和5可以重用之前执行的范例PL/SQL代码3中目标SQL(即INSERT INTO T_BG_20170610_LHR VALUES(:N,:V))的解析树和执行计划。在执行范例PL/SQL代码6时是硬解析,这意味着对于此目标SQL而言,其所在的Parent cursor下会有4个Child Cursor:

LHR@orclasm > col sql_text format a60

LHR@orclasm > SELECT SQL_TEXT,SQL_ID,VERSION_COUNT,EXECUTIONS FROM V$SQLAREA WHERE SQL_TEXT LIKE 'INSERT INTO T_BG_20170610_LHR VALUES%';

 

SQL_TEXT                                                     SQL_ID        VERSION_COUNT EXECUTIONS

------------------------------------------------------------ ------------- ------------- ----------

INSERT INTO T_BG_20170610_LHR VALUES(:N,:V)                  01g03pruhphqc             4          6

 

 

LHR@orclasm > SELECT SQL_TEXT,SQL_ID,D.CHILD_NUMBER,D.CHILD_ADDRESS,EXECUTIONS FROM V$SQL D WHERE SQL_ID = '01g03pruhphqc';

 

SQL_TEXT                                                     SQL_ID        CHILD_NUMBER CHILD_ADDRESS    EXECUTIONS

------------------------------------------------------------ ------------- ------------ ---------------- ----------

INSERT INTO T_BG_20170610_LHR VALUES(:N,:V)                  01g03pruhphqc            0 00000000AA902CE8          1    <<----对应PL/SQL代码1

INSERT INTO T_BG_20170610_LHR VALUES(:N,:V)                  01g03pruhphqc            1 00000000AAA47348          1    <<----对应PL/SQL代码2

INSERT INTO T_BG_20170610_LHR VALUES(:N,:V)                  01g03pruhphqc            2 00000000AAAF7A28          3    <<----对应PL/SQL代码3、4、5

INSERT INTO T_BG_20170610_LHR VALUES(:N,:V)                  01g03pruhphqc            3 0000000095DA4B00          1    <<----对应PL/SQL代码6

 

LHR@orclasm > SELECT d.SQL_ID,D.CHILD_NUMBER,D.BIND_LENGTH_UPGRADEABLE FROM V$SQL_SHARED_CURSOR D WHERE D.SQL_ID = '01g03pruhphqc';

 

SQL_ID        CHILD_NUMBER B

------------- ------------ -

01g03pruhphqc            0 N

01g03pruhphqc            1 Y

01g03pruhphqc            2 Y

01g03pruhphqc            3 Y

下面查询分配的内存空间大小:

LHR@orclasm > SELECT B.CHILD_NUMBER,B.CHILD_ADDRESS,D.BIND_NAME,D.POSITION,D.DATATYPE,D.MAX_LENGTH FROM v$sql_bind_metadata d,V$SQL b WHERE d.ADDRESS=b.CHILD_ADDRESS AND b.SQL_ID='01g03pruhphqc' ORDER BY B.CHILD_NUMBER,D.POSITION;

 

CHILD_NUMBER CHILD_ADDRESS    BIND_NAME                        POSITION   DATATYPE MAX_LENGTH

------------ ---------------- ------------------------------ ---------- ---------- ----------

           0 00000000AA902CE8 N                                       1          2         22

           0 00000000AA902CE8 V                                       2          1         32

           1 00000000AAA47348 N                                       1          2         22

           1 00000000AAA47348 V                                       2          1        128

           2 00000000AAAF7A28 N                                       1          2         22

           2 00000000AAAF7A28 V                                       2          1       2000

           3 0000000095DA4B00 N                                       1          2         22

           3 0000000095DA4B00 V                                       2          1       4000

从上述查询结果可以看到,Child Cursor 0中文本型绑定变量V确实被分配了32字节的内存空间,Child Cursor 1中文本型绑定变量V确实被分配了128字节的内存空间,Child Cursor 2中文本型绑定变量V被分配了2000字节的内存空间,Child Cursor 3中文本型绑定变量V被分配了4000字节的内存空间,同时这三个Child Cursor中的数值型绑定变量N统一被分配了22字节的内存空间。

通过上述示例可以看出:为了避免不必要的硬解析,在PL/SQL代码中处理带文本型绑定变量的目标SQL时,应该将这些文本型绑定变量的定义长度保持在同一个等级,当然,这里最好是定义成一个统一的长度,比如VARCHAR2(4000)。



>

     

>

                    

                  

>

      

           
           
           

>

                  

                            
                           
                            
                            
                            
                            

>
>

>

>

>

                                       

            

>

>

>

                                       

                                       

>

>

>

                                       

                                       

>

>

>

                                       

                                       

>

>

><

>

>

     

      
      
        
             
           
          
           
            

>

>>>>

>

>
>

>

                   

                   
            
             

  

      
      
    
      
      
   
    
     
      
      
    

>

        

        
      

  

      
      
     
      
      
   
    
     
      
      
    



    

时间: 2024-09-23 14:22:20

Oracle绑定变量分级(Bind Graduation)的相关文章

Oracle绑定变量与直方图

一.绑定变量的窥探(peek) 1.Oracle在处理带有绑定变量的SQL时候,只会在硬解析的时候才会"窥探"一下SQL中绑定变量的值,然后会根据窥探到的值来决定整个SQL的执行计划.参数:_optim_peek_user_binds  2.绑定变量窥探的案例 create table t8(id int ,name varchar2(100)); begin for i in 1 .. 1000 loop  insert into t8 values(i,'gyj'||i);  en

C# 使用oracle绑定变量后,查询效率变慢如何解决?满意可加分

问题描述 如题.本人写了一个C#使用oracle绑定变量的DAL,在应用里使用此连接.查询速度没有提升,反而变慢,是怎么回事?如何解决?急需解决,满意可加分. 解决方案 解决方案二:怎么绑的,代码呢解决方案三:代码如下:publicSystem.Data.DataSetQuery(stringSQLString,List<DBParameter>dbParam){using(OracleConnectionconnection=newOracleConnection(connectionStr

绑定变量和BIND PEEKING

http://www.oraclefans.cn/forum/showtopic.jsp?rootid=5467&CPages=1 http://blog.csdn.net/tianlesoftware/article/details/5544307 使用绑定变量可以减少SQL PARSE,但是使用绑定变量有一个不好的地方,就是对于访问具有倾斜的列,可能使用错误的执行计划.在Oracle 9i之前,如果WHERE 条件里面全部使用绑定变量,那么只能使用固定的选择性参数来确定执行计划. =操作和&g

Oracle 绑定变量窥探

     Bind Peeking是Oracle 9i中引入的新特性,一直持续到Oracle 10g R2.它的作用就是在SQL语句硬分析的时候,查看一下当前SQL谓词的值 ,以便生成最佳的执行计划.而在oracle 9i之前的版本中,Oracle 只根据统计信息来做出执行计划. 一.绑定变量窥探     使用SQL首次运行时的值来生成执行计划.后续再次运行该SQL语句则使用首次执行计划来执行.     影响的版本:Oracle 9i, Oracle 10g     对于绑定变量列中的特殊值或非

ORACLE绑定变量隐式转换导致性能问题

   年后一次系统升级后,监控数据库的工具DPA发现数据库的Total Wait时间突然飙增,如下截图所示,数据库的总体等待时间对比升级前飙增了非常多 另 外就是发现出现了较多的等待事件,主要有latch: cache buffers chains. latch: shared pool .db file scattered read.根据这边的监控发现TOP SQL里面从升级前的0次变为了一天的一万多次(有些甚至更多),分析过后我们就找开发人员了解一下系统升级变跟的内容和改动 开 发人员坚定的

绑定变量优缺点、使用、绑定变量窥探、 Oracle自适应共享游标

绑定变量优缺点.使用.绑定变量窥探     绑定变量是Oracle解决硬解析的首要利器,能解决OLTP系统中library cache的过度耗用以提高性能.然刀子磨的太快,使起来锋利,却容易折断.凡事皆有利弊二性,因地制宜,因时制宜,全在如何权衡而已.本文讲述了绑定变量的使用方法,以及绑定变量的优缺点.使用场合.   一.绑定变量     提到绑定变量,就不得不了解硬解析与软解析.硬解析简言之即一条SQL语句没有被运行过,处于首次运行,则需要对其进行语法分析,语义识别,跟据统计信息生成最佳的执行

Oracle 系统变量函数用法指南_oracle

Oracle函数多种多样,系统变量函数就是其中之一,介绍三种最常见的系统变量函数. Oracle系统变量函数: 1)SYSDATE 该函数返回当前的日期和时间.返回的是Oracle服务器的当前日期和时间. select sysdate from dual; insert into purchase values ('Small Widget','SH',sysdate, 10); insert into purchase values ('Meduem Wodget','SH',sysdate-

Oracle: 变量绑定

Parent-Child cursor (父子游标) 父游标:只要SQL语句文本相同,它们就对应 同一个parent cursor. 子游标:在某些情况下,虽然SQL语句的文本相同,但是因为其它 因素不同(这些因素可以在视图V$SQL_SHARED_CURSOR中查看),导致产生不同的child cursor.(重新生成child cursor,也就意味着一次硬解析) cursor_sharing 对 于是否使用绑定变量这个问题,最好是交给应用程序决定,在数据库层面是很难正确判断. (这也是为什

Oracle获取绑定变量的各种方法

Oracle获取绑定变量的各种方法 当Oracle解析和执行含有绑定变量的目标SQL时,如果满足如下两个条件之一,那么该SQL中的绑定变量的具体输入值就会被Oracle捕获: l 当含有绑定变量的目标SQL以硬解析的方式被执行时. l 当含有绑定变量的目标SQL以软解析或软软解析的方式重复执行时,Oracle在默认情况下至少得间隔15分钟才会捕获一次.这个15分钟受隐含参数"_CURSOR_BIND_CAPTURE_INTERVAL"控制,默认值为900秒,即15分钟. SYS@orc