您的位置:首页 > 数据库 > Oracle

oracle 如何获取绑定变量的值

2014-08-11 17:01 302 查看
以下转自:http://blog.csdn.net/zero_plus/article/details/6305122 作者:zero_plus

绑定变量为ORACLE系统提供了很多优点,减少资源占用,降低资源争用,加速了SQL解析的过程,但同时也带来了某些缺点,比如对于数据分布严重不均衡 的列可能产生不正确的执行计划,很难得到绑定变量实际传入的值。在执行计划不正确的时候,我们要判断到底是因为不均衡的列的窥视带来的问题,还是统计信息 的问题,还是BUG或者其他问题,这时候就要看看到底绑定变量传入的值是什么。当然,10046或者去TRACE一个SESSION都可以得到精确的值, 但在OLTP系统中,SESSION的值瞬间即逝,很难抓的到,而我们也不需要百分百准确的值,只是看看这些值大部分是落在了不均衡的列的哪一端,然后去 确定正确的执行计划。ORACLE也提供了一个视图V$SQL_BIND_CAPTURE来查看这个绑定变量的值,但这个值15分钟才更新一次,假如你要 统计10次来看看不均衡列的传入值的分布,那要等倆半钟头,下面来介绍一下怎么样使得这个时间稍快些。

ORACLE为我们提供了一个隐含参数_cursor_bind_capture_interval,这个就是控制绑定变量抓取频率的参数,默认值是900,单位是秒,也就是15分钟。下面通过一个例子来看看调整这个参数对抓取绑定变量的影响:
首先来造数据:
SQL> create table t(id number);

Table created

SQL> create sequence seq_t;

Sequence created

SQL> begin
2 for i in 1..10000 loop
3 insert into t values(seq_t.nextval);
4 end loop;
5 end;
6 /
PL/SQL procedure successfully completed

SQL> commit;

Commit complete

然后写一个存储过程来定时的通过V$SQL_BIND_CAPTURE去抓绑定变量的值:
CREATE OR REPLACE PROCEDURE PRC_BIND_TEST IS
V_COUNT NUMBER;
V_TEMP NUMBER;
V_BIND NUMBER;
BEGIN
V_COUNT := 1;
FOR R IN 1 .. 10 LOOP
SELECT 1 INTO V_TEMP FROM T WHERE ID = V_COUNT;
V_COUNT := V_COUNT + 1;
DBMS_LOCK.SLEEP(5); --每5秒钟运行一次上面的SELECT
SELECT VALUE_STRING
INTO V_BIND
FROM V$SQL_BIND_CAPTURE
WHERE SQL_ID = 'agq1278fxbpkg'; --SQL_ID事先得到,然后根据上面的SQL的SQL_ID去抓绑定变量的值
DBMS_OUTPUT.PUT_LINE(TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') || ':' ||
V_BIND); --把系统时间和绑定变量的值打印出来
END LOOP;
END PRC_BIND_TEST;

首先修改隐含参数为5,然后执行上面的存储过程:
SQL> alter system set "_cursor_bind_capture_interval"=5 scope=both;

System altered.

SQL> set serveroutput on;
SQL> exec prc_bind_test;

2010-03-23 14:44:01:1
2010-03-23 14:44:06:2
2010-03-23 14:44:11:3
2010-03-23 14:44:16:4
2010-03-23 14:44:21:5
2010-03-23 14:44:26:6
2010-03-23 14:44:31:7
2010-03-23 14:44:36:8
2010-03-23 14:44:41:9
2010-03-23 14:44:46:10

PL/SQL procedure successfully completed

可以看到,每5秒执行一次SELECT,这时往绑定变量传入一个值,然后正好间隔5秒去视图中抓一次,抓到的值是完全连续的,说明系统确实是每5秒去抓一次绑定变量的值然后存放到了V$SQL_BIND_CAPTURE视图中,然后修改隐含参数为10秒,再次执行存储过程:
SQL> alter system set "_cursor_bind_capture_interval"=10 scope=both;

System altered.

SQL> exec prc_bind_test;

2010-03-23 14:45:50:1
2010-03-23 14:45:55:1
2010-03-23 14:46:00:3
2010-03-23 14:46:05:3
2010-03-23 14:46:10:5
2010-03-23 14:46:15:5
2010-03-23 14:46:20:7
2010-03-23 14:46:25:7
2010-03-23 14:46:30:9
2010-03-23 14:46:35:9

PL/SQL procedure successfully completed

可以看到每5秒去抓一次,抓到的绑定变量的值是10秒才更换一次,说明系统确实是每10秒钟去抓一次绑定变量的值。

到此,可以证明_cursor_bind_capture_interval参数确实是控制绑定变量的值抓取频率的参数,而且这个值可以动态修改的。测试过程中把这个值设置为1秒,也可以得到正确的结果,说明极端情况下可以设置为1秒。但估计频繁的抓取对系统性能会有些影响,如果实在需要,可以根据系统压力情况去一步步的缩小这个值,直到自己满意的范围。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: