|
在SQL*Plus直接输入SELECT命令进行实验,将会受到SQL*Plus的影响。我以前实验的结果,在9i环境下,每一条SELECT语句在执行完毕后,ORACLE并不关闭游标,只到下一条语句执行时,才关闭上一条语句的游标。10G下我没试过,但是SQL*Plus肯定会对结果造成一定的影响,我用下面两个脚本,观察硬解析、软解析、快速软解析和无解析时对Library cache lock latch、Library cache pin latch和Library cache latch这三个闩的影响:
--------(脚本1)------------------
declare
mgets varchar2(10);
mname varchar2(100);
msql varchar2(200);
mcur number;
mstat number;
jg varchar2(100);
kg varchar2(100):=' ';
begin
for i in 1..20 loop
mcur:=dbms_sql.open_cursor;
msql:='select name,gets from v$latch where name in (''library cache'',''library cache lock'',''library cache pin'')';
dbms_sql.parse(mcur,msql,dbms_sql.native);
dbms_sql.define_column(mcur,1,mname,100);
dbms_sql.define_column(mcur,2,mgets,10);
mstat:=dbms_sql.execute(mcur);
for j in 1..3 loop
mstat:=dbms_sql.fetch_rows(mcur);
dbms_sql.column_value(mcur,1,mname);
dbms_sql.column_value(mcur,2,mgets);
dbms_output.put(jg||' '||mname||' : '||mgets);
end loop;
dbms_output.put_line('');
dbms_sql.close_cursor(mcur);
end loop;
end;
/
将上面的程序略做修改,让循环内每次游标的文本都不一样:
--------(脚本2)------------------
declare
mgets varchar2(10);
mname varchar2(100);
msql varchar2(200);
mcur number;
mstat number;
jg varchar2(100);
kg varchar2(100):=' ';
begin
for i in 1..20 loop
mcur:=dbms_sql.open_cursor;
msql:='select name,gets'||kg||'from v$latch where name in (''library cache'',''library cache lock'',''library cache pin'')';
dbms_sql.parse(mcur,msql,dbms_sql.native);
kg:=kg||' ';
dbms_sql.define_column(mcur,1,mname,100);
dbms_sql.define_column(mcur,2,mgets,10);
mstat:=dbms_sql.execute(mcur);
for j in 1..3 loop
mstat:=dbms_sql.fetch_rows(mcur);
dbms_sql.column_value(mcur,1,mname);
dbms_sql.column_value(mcur,2,mgets);
dbms_output.put(jg||' '||mname||' : '||mgets);
end loop;
dbms_output.put_line('');
dbms_sql.close_cursor(mcur);
end loop;
end;
/
还可以将上面两段代码中的SQL语句换成:'select gets, pins from v$librarycache where namespace=''SQL AREA'''; 观察一下Library cache lock/pin会和 latch有什么不同的结果,测试数据如下:
- 利用脚本1查看在循环中共享游标的情况:
- 在游标被缓存到PGA后:
- Library cache Library cache Library cache
- Gets Pins Lock latch Pin Latch latch
- 在循环中打开游标: 0 1 0 2 2
- 在循环中解析 : 0 1 0 2 2 (将mcur:=dbms_sql.open_cursor移到循环之外)
- 只在循环中执行、抓取: 0 0 0 0 0(将dbms_sql.parse(mcur,msql,dbms_sql.native)移到循环之外)
- 在游标未被缓存到PGA(即将session_cached_cursors设为0)时:
- 在循环中打开游标: 0 1 4 2 2
- 在循环中解析 : 0 1 4 2 2
- 只在循环中执行、抓取: 0 0 0 0 0
- 利用脚本2查看硬解析或不在循环中共享游标的情况(session_cached_cursors为0):
- 硬解析时的(每测前用alter system flush shared_pool清空共享池)
- 硬解析 : 1 2 12 13 33
- 第一次软解析: 0 1 4 4 11
- 第二次软解析: 0 1 4 2 6
- (第三次软件的结果同第二次)
- 利用脚本2查看硬解析或不在循环中共享游标的情况(session_cached_cursors为50):
- 硬解析时的(每测前用alter system flush shared_pool清空共享池)
- 硬解析 : 1 2 12 13 33
- 第一次软解析: 0 1 6 4 11
- 第二次软解析: 0 1 2 2 4
- 第三次软解析: 0 1 0 2 2
- (第四次软件的结果同第二次)
复制代码
根据测试结果可以看到,很难猜测到Library cache Lock/Pin Latch以及Library cache闩的作用。不过,通过实验,比较肯定的有两点发现:
1、ORACLE在循环中共享游标执行计划时,所需要的Latch更少。而同样是软解析,在非循环中需要更多的Latch。
2、Open cursor操作应该只是在PGA中为私有游标区分配空间,并没有操作共享SQL区。因此在循环中打开游标,和在循环之外打开游标,Latch的次数是一样的。
3、即使session_cached_cursors为0,当在循环中共享执行计划时,应该也会缓存游标。
[ 本帖最后由 晶晶小妹 于 2008-6-24 09:40 编辑 ] |
|