游标的生命周期
打开游标——>解析游标——>定义输出变量——>绑定输入变量——>执行游标——>获取游标——>关闭游标
利用DBMS_SQL包显示编码
DECLARE
l_ename EMP.ENAME%TYPE := 'SCOTT';
l_empno EMP.EMPNO%TYPE;
l_cursor INTEGER;
l_retval INTEGER;
BEGIN
--open
l_cursor := DBMS_SQL.OPEN_CURSOR;
--parse
DBMS_SQL.PARSE (l_cursor, 'select empno from emp where ename=:ename', 1);
--output variable
DBMS_SQL.define_column (l_cursor, 1, l_empno);
--bind variable
DBMS_SQL.BIND_VARIABLE (l_cursor, ':ename', l_ename);
--excute
l_retval := DBMS_SQL.EXECUTE (l_cursor);
--fetch
IF DBMS_SQL.FETCH_ROWS (l_cursor) > 0
THEN
DBMS_SQL.COLUMN_VALUE (l_cursor, 1, l_empno);
END IF;
--close
DBMS_SQL.CLOSE_CURSOR (l_cursor);
END;
利用隐含游标
DECLARE
l_ename EMP.ENAME%TYPE := 'SCOTT';
l_empno EMP.EMPNO%TYPE;
BEGIN
SELECT empno
INTO l_empno
FROM emp
WHERE ename = l_name;
END;
解析的过程
包含VPD的约束条件——>语法语义以及访问权限检查——>将父游标保存到库缓存——>逻辑优化——>物理优化——>将子游标保存到库缓存
v$sqlarea(父) sql_id (address,hash_value)
v$sql(子) sql_id,child_number(address,hash_value,child_number)
硬解析成本高的原因:
1,逻辑优化和物理优化非常消耗CPU资源。
2,需要分配内存保存父游标和子游标在库缓存(库缓存在所有session之间共享,内存非配必须串行)。
共享游标
与父游标有关的关键信息是:SQL文本
与子游标有关的关键信息是:执行计划及其有关的执行环境
v$sql_shared_cursor查看游标无法共享的原因
绑定变量
优点:可以共享游标,避免硬解析以及与之相关的额外开销。
缺点:where条件的子句中会一些至关重要的信息对优化器不可见。字面量可以提高估算的准确性
绑定变量窥测(bind variable peeking):在物理优化阶段,优化器会窥测绑定变量的值,将它当做字面量来使用。
缺点是生成的执行计划会依赖第一次生成执行计划所提供的值。
为了解决这个问题,Oracle11g引入一种被称为扩展的游标共享(extended cursor sharing ,也称适用性游标共享adaptive cursor sharing)的新功能。
它的目的是在重用一个共享游标但是会导致效率低下时能够进行自动识别。
Oracle11g v$sql有如下栏位:(10g只有70个栏位,11g有87个栏位)
IS_BIND_SENSITIVE,
IS_BIND_AWARE,
IS_SHAREABLE,
最佳实践
不涉及where子句的时候,应该使用绑定变量,直方图信息对优化器有很大影响的情况下,最好不使用绑定变量。
sql处理少量数据,使用绑定变量通常是较优的选择
sql处理大量数据,使用绑定变量对总响应时间几乎没有影响
读写数据块
逻辑读(logical read):服务器进程访问到buffer cache中一个数据块的时候,就发生了一次逻辑读。注意:逻辑读既用于读数据块也用于写数据块。
物理读(physical read):当服务器进程需要访问buffer cache不存在的数据块时产生一次物理读。相应地,它需要打开数据文件,读这个数据块,并放入buffer cache
物理写(physical write):服务器进程不负责写,后台进程DBWR写回数据文件
直接读(direct read)
直接写(direct write)