ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

【DB笔试面试583】在Oracle中,什么是绑定变量分级?

2021-04-09 22:55:17  阅读:177  来源: 互联网

标签:583 -- 绑定 DB 内存空间 SQL Oracle 变量 字节


watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

♣          题目         部分

在Oracle中,什么是绑定变量分级?


     
♣          答案部分          


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

等级

定义长度(Byte)

分配内存大小(Byte)

1

(0,32]

32

2

[33,128]

128

3

[129,2000]

2000

4

大于2000

分配的内存空间大小取决于对应文本型绑定变量所传入的实际绑定变量值的大小。如果实际传入的绑定变量值小于或等于2000字节,那么Oracle会为其分配2000字节的内存空间。如果实际传入的绑定变量值大于2000字节,那么Oracle会为其分配4000字节的内存空间。

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)中的解析树和执行计划就不能被重用了。原因是子游标中除了会存储目标SQL的解析树和执行计划之外,还会存储该SQL所使用的绑定变量的类型和长度,这意味着即使该SQL的SQL文本没有发生任何改变,只要其SQL文本中文本型绑定变量的定义长度发生了变化,那么该SQL再次执行时就可能还是做硬解析(新生成一个子游标)。

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

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

 1CREATE TABLE T_BG_20170610_LHR(N NUMBER(10),V VARCHAR2(3000));
 2--SQL_TEXT1:硬解析
 3DECLARE
 4  N NUMBER(10) :=1;--分配22字节的内存空间
 5  V VARCHAR2(32) :='XIAOMAIMIAO1';--分配32字节的内存空间
 6BEGIN
 7  EXECUTE IMMEDIATE 'INSERT INTO T_BG_20170610_LHR VALUES(:N,:V)' USING N, V;
 8  COMMIT;
 9END;
10/
11--SQL_TEXT2:硬解析
12DECLARE
13  N NUMBER(10) :=2;--分配22字节的内存空间
14  V VARCHAR2(33) :='XIAOMAIMIAO2';--分配128字节的内存空间
15BEGIN
16  EXECUTE IMMEDIATE 'INSERT INTO T_BG_20170610_LHR VALUES(:N,:V)' USING N, V;
17  COMMIT;
18END;
19/
20
21--SQL_TEXT3:硬解析
22DECLARE
23  N NUMBER(10) :=3;--分配22字节的内存空间
24  V VARCHAR2(129) :='XIAOMAIMIAO3';--分配2000字节的内存空间
25BEGIN
26  EXECUTE IMMEDIATE 'INSERT INTO T_BG_20170610_LHR VALUES(:N,:V)' USING N, V;
27  COMMIT;
28END;
29/
30
31--SQL_TEXT4:软解析
32DECLARE
33  N NUMBER(10) :=4;--分配22字节的内存空间
34  V VARCHAR2(2001) :='XIAOMAIMIAO4';--分配2000字节的内存空间
35BEGIN
36  EXECUTE IMMEDIATE 'INSERT INTO T_BG_20170610_LHR VALUES(:N,:V)' USING N, V;
37  COMMIT;
38END;
39/
40--SQL_TEXT5:软解析
41DECLARE
42  N NUMBER(10) :=5;--分配22字节的内存空间
43  V VARCHAR2(32767) :='XIAOMAIMIAO5';--分配2000字节的内存空间
44BEGIN
45  EXECUTE IMMEDIATE 'INSERT INTO T_BG_20170610_LHR VALUES(:N,:V)' USING N, V;
46  COMMIT;
47END;
48/
49--SQL_TEXT6: 硬解析
50DECLARE
51  N NUMBER(10) :=6;  --分配22字节的内存空间
52  V VARCHAR2(32767) :=RPAD('XIAOMAIMIAO6',2002,'8');  --字符串长度为2002,分配4000字节的内存空间
53BEGIN
54  EXECUTE IMMEDIATE 'INSERT INTO T_BG_20170610_LHR VALUES(:N,:V)' USING N, V;
55  COMMIT;
56END;
57/
     

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

 1LHR@orclasm > col v format a13
 2LHR@orclasm > select * from T_BG_20170610_LHR T WHERE T.N<=5;
 3
 4         N V
 5---------- -------------
 6         1 XIAOMAIMIAO1
 7         2 XIAOMAIMIAO2
 8         3 XIAOMAIMIAO3
 9         4 XIAOMAIMIAO4
10         5 XIAOMAIMIAO5
11LHR@orclasm > SELECT T.N,LENGTH(T.V) FROM T_BG_20170610_LHR T;
12
13         N LENGTH(T.V)
14---------- -----------
15         1          12
16         2          12
17         3          12
18         4          12
19         5          12
20         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:

 1LHR@orclasm > col sql_text format a60
 2LHR@orclasm > SELECT SQL_TEXT,SQL_ID,VERSION_COUNT,EXECUTIONS FROM V$SQLAREA WHERE SQL_TEXT LIKE 'INSERT INTO T_BG_20170610_LHR VALUES%';
 3
 4SQL_TEXT                                                     SQL_ID        VERSION_COUNT EXECUTIONS
 5------------------------------------------------------------ ------------- ------------- ----------
 6INSERT INTO T_BG_20170610_LHR VALUES(:N,:V)                  01g03pruhphqc             4          6
 7
 8
 9LHR@orclasm > SELECT SQL_TEXT,SQL_ID,D.CHILD_NUMBER,D.CHILD_ADDRESS,EXECUTIONS FROM V$SQL D WHERE SQL_ID = '01g03pruhphqc';
10
11SQL_TEXT                                                     SQL_ID        CHILD_NUMBER CHILD_ADDRESS    EXECUTIONS
12------------------------------------------------------------ ------------- ------------ ---------------- ----------
13INSERT INTO T_BG_20170610_LHR VALUES(:N,:V)                  01g03pruhphqc            0 00000000AA902CE8          1    <<----对应PL/SQL代码1
14INSERT INTO T_BG_20170610_LHR VALUES(:N,:V)                  01g03pruhphqc            1 00000000AAA47348          1    <<----对应PL/SQL代码2
15INSERT INTO T_BG_20170610_LHR VALUES(:N,:V)                  01g03pruhphqc            2 00000000AAAF7A28          3    <<----对应PL/SQL代码3、4、5
16INSERT INTO T_BG_20170610_LHR VALUES(:N,:V)                  01g03pruhphqc            3 0000000095DA4B00          1    <<----对应PL/SQL代码6
17
18LHR@orclasm > SELECT d.SQL_ID,D.CHILD_NUMBER,D.BIND_LENGTH_UPGRADEABLE FROM V$SQL_SHARED_CURSOR D WHERE D.SQL_ID = '01g03pruhphqc';
19
20SQL_ID        CHILD_NUMBER B
21------------- ------------ -
2201g03pruhphqc            0 N
2301g03pruhphqc            1 Y
2401g03pruhphqc            2 Y
2501g03pruhphqc            3 Y
26
27--下面查询分配的内存空间大小:
28LHR@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;
29
30CHILD_NUMBER CHILD_ADDRESS    BIND_NAME                        POSITION   DATATYPE MAX_LENGTH
31------------ ---------------- ------------------------------ ---------- ---------- ----------
32           0 00000000AA902CE8 N                                       1          2         22
33           0 00000000AA902CE8 V                                       2          1         32
34           1 00000000AAA47348 N                                       1          2         22
35           1 00000000AAA47348 V                                       2          1        128
36           2 00000000AAAF7A28 N                                       1          2         22
37           2 00000000AAAF7A28 V                                       2          1       2000
38           3 0000000095DA4B00 N                                       1          2         22
39           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)。

标签:583,--,绑定,DB,内存空间,SQL,Oracle,变量,字节
来源: https://blog.51cto.com/lhrbest/2695532

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有