ITPub博客

首页 > 数据库 > Oracle > SQL绑定变量的使用

SQL绑定变量的使用

Oracle 作者:oraclesuperman 时间:2015-06-10 17:18:19 0 删除 编辑
SQL> create global temporary table sess_event on commit preserve rows as select * from v$session_event where 1=0;

Table created

SQL> insert into sess_event
  2  select * from v$session_event
  3  where sid=(select sid from v$mystat where rownum=1);

9 rows inserted

SQL>
SQL> SELECT NAME,VALUE FROM V$MYSTAT A,V$STATNAME B WHERE A.STATISTIC#=B.STATISTIC#
  2  AND NAME LIKE 'parse count%'
  3  ;

NAME                                                                  VALUE
---------------------------------------------------------------- ----------
parse count (total)                                                   32127
parse count (hard)                                                    30365
parse count (failures)                                                    1

SQL>
SQL> begin
  2  for i in 1..10000 loop
  3          execute immediate 'insert into test values('||i||','||i||')';
  4  end loop;
  5  commit;
  6  end;
  7  /

PL/SQL procedure successfully completed

SQL>
SQL> SELECT NAME,VALUE FROM V$MYSTAT A,V$STATNAME B WHERE A.STATISTIC#=B.STATISTIC#
  2  AND NAME LIKE 'parse count%';

NAME                                                                  VALUE
---------------------------------------------------------------- ----------
parse count (total)                                                   42201
parse count (hard)                                                    40379
parse count (failures)                                                    1

没有使用绑定变量(这种写法往往有人误认为使用了绑定,这里就不多解释了)
总解析次数:10074
硬解析次数:10014
上边2个值除了我们的循环10000次外,还包括其他一些系统表的读写,所以解析次数大于10000,但是我们要注意下面的结果,对于每个SQL
都有一个版本,也就是ORACLE对于每个不同的SQL分别执行了硬解析,下面是共享池最后缓存的数据(部分已经被覆盖)

SQL> select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper(sql_text) like '%TEST%';

SQL_TEXT                                                                         VERSION_COUNT PARSE_CALLS EXECUTIONS
-------------------------------------------------------------------------------- ------------- ----------- ----------
insert into test values(9630,9630)                                                           1           1          1
insert into test values(9950,9950)                                                           1           1          1
insert into test values(9625,9625)                                                           1           1          1
insert into test values(9592,9592)                                                           1           1          1
insert into test values(9940,9940)                                                           1           1          1
insert into test values(9897,9897)                                                           1           1          1
insert into test values(9679,9679)                                                           1           1          1
insert into test values(9850,9850)                                                           1           1          1
insert into test values(9744,9744)                                                           1           1          1
insert into test values(9938,9938)                                                           1           1          1
insert into test values(9977,9977)                                                           1           1          1
insert into test values(9907,9907)                                                           1           1          1
insert into test values(9809,9809)                                                           1           1          1
insert into test values(9800,9800)                                                           1           1          1
insert into test values(9645,9645)                                                           1           1          1
insert into test values(9724,9724)                                                           1           1          1
insert into test values(9799,9799)                                                           1           1          1
insert into test values(9818,9818)                                                           1           1          1
insert into test values(9642,9642)                                                           1           1          1
insert into test values(9624,9624)                                                           1           1          1

中间内容略

SQL_TEXT                                                                         VERSION_COUNT PARSE_CALLS EXECUTIONS
-------------------------------------------------------------------------------- ------------- ----------- ----------
insert into test values(9838,9838)                                                           1           1          1
insert into test values(9716,9716)                                                           1           1          1
insert into test values(9691,9691)                                                           1           1          1
insert into test values(9831,9831)                                                           1           1          1
insert into test values(9992,9992)                                                           1           1          1
insert into test values(9883,9883)                                                           1           1          1
insert into test values(9865,9865)                                                           1           1          1
insert into test values(9901,9901)                                                           1           1          1
insert into test values(9657,9657)                                                           1           1          1
insert into test values(10000,10000)                                                         1           1          1
insert into test values(9659,9659)                                                           1           1          1
insert into test values(9746,9746)                                                           1           1          1
insert into test values(9695,9695)                                                           1           1          1
insert into test values(9869,9869)                                                           1           1          1
insert into test values(9804,9804)                                                           1           1          1
insert into test values(9843,9843)                                                           1           1          1

435 rows selected

SQL> truncate talbe sess_event;

truncate talbe sess_event

ORA-03290: 无效的截断命令 - 缺失 CLUSTER 或 TABLE 关键字

SQL> truncate table sess_event;

Table truncated

SQL> alter system flush shared_pool;

System altered

SQL>
SQL> insert into sess_event
  2  select * from v$session_event
  3  where sid=(select sid from v$mystat where rownum=1);

10 rows inserted

SQL>
SQL> SELECT NAME,VALUE FROM V$MYSTAT A,V$STATNAME B WHERE A.STATISTIC#=B.STATISTIC#
  2  AND NAME LIKE 'parse count%';

NAME                                                                  VALUE
---------------------------------------------------------------- ----------
parse count (total)                                                   42643
parse count (hard)                                                    40456
parse count (failures)                                                    2

SQL>
SQL> begin
  2  for i in 1..10000 loop
  3          execute immediate 'insert into test values(:v1,:v2)' using i,i;
  4  end loop;
  5  commit;
  6  end;
  7  /

PL/SQL procedure successfully completed

SQL>
SQL> SELECT NAME,VALUE FROM V$MYSTAT A,V$STATNAME B WHERE A.STATISTIC#=B.STATISTIC#
  2  AND NAME LIKE 'parse count%';

NAME                                                                  VALUE
---------------------------------------------------------------- ----------
parse count (total)                                                   42688
parse count (hard)                                                    40466
parse count (failures)                                                    2

下面看下使用绑定变量的情况(真正使用了绑定)
总解析次数:45
硬解析次数:10
我们可以看出差异是多么大了,呵呵,对于SQL本身只有一次软解析,执行次数为10000

SQL> select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper(sql_text) like '%TEST%';

SQL_TEXT                                                                         VERSION_COUNT PARSE_CALLS EXECUTIONS
-------------------------------------------------------------------------------- ------------- ----------- ----------
begin for i in 1..10000 loop  execute immediate 'insert into test values(:v1,:v2             1           1          1
update sys.job$ set failures=0, this_date=null, flag=:1, last_date=:2,  next_dat             1           1          1
insert into test values(:v1,:v2)                                                             1           1      10000
select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper(             1           1          1
select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper(             1           1          1

SQL> alter system flush shared_pool;

System altered

但是我们要注意一个情况,即时同样的SQL如果没有使用绑定变量,ORACLE也会对其执行一次软解析的,但是没有硬解析,如下:
每执行一次SQL,也会同时产生其他写系统表等很多相关的软解析包括查询SQL本身。硬解析不变。
SQL> insert into test values('1','1111111111');

1 row inserted

SQL> commit;

Commit complete

SQL> select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper(sql_text) like '%TEST%';

SQL_TEXT                                                                         VERSION_COUNT PARSE_CALLS EXECUTIONS
-------------------------------------------------------------------------------- ------------- ----------- ----------
update sys.job$ set failures=0, this_date=null, flag=:1, last_date=:2,  next_dat             1           1          1
insert into test values('1','1111111111')                                                    1           1          1
select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper(             1           1          1
select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper(             1           1          1

SQL> insert into test values('1','1111111111');

1 row inserted

SQL> commit;

Commit complete

SQL> select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper(sql_text) like '%TEST%';

SQL_TEXT                                                                         VERSION_COUNT PARSE_CALLS EXECUTIONS
-------------------------------------------------------------------------------- ------------- ----------- ----------
update sys.job$ set failures=0, this_date=null, flag=:1, last_date=:2,  next_dat             1           1          1
insert into test values('1','1111111111')                                                    1           2          2
select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper(             1           1          1
select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper(             1           2          2

SQL>

SQL> SELECT NAME,VALUE FROM V$MYSTAT A,V$STATNAME B WHERE A.STATISTIC#=B.STATISTIC#
  2  AND NAME LIKE 'parse count%';

NAME                                                                  VALUE
---------------------------------------------------------------- ----------
parse count (total)                                                   42906
parse count (hard)                                                    40520
parse count (failures)                                                    2

SQL> insert into test values('1','1111111111');

1 row inserted

SQL> commit;

Commit complete

SQL> select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper(sql_text) like '%TEST%';

SQL_TEXT                                                                         VERSION_COUNT PARSE_CALLS EXECUTIONS
-------------------------------------------------------------------------------- ------------- ----------- ----------
begin dbsnmp.mgmt_response.get_latest_curs(:a); end;                                         1           1          1
/* OracleOEM */  BEGIN   IF (:1 = 'READ WRITE') THEN     ----     -- For a read-             1           1          1
/* OracleOEM */  DECLARE         instance_number NUMBER;  latest_task_id NUMBER;             1           1          1
update sys.job$ set failures=0, this_date=null, flag=:1, last_date=:2,  next_dat             1           4          4
insert into test values('1','1111111111')                                                    1           3          3
DELETE FROM MGMT_DB_LATEST_HDM_FINDINGS WHERE TARGET_GUID = :B2 AND COLLECTION_T             2           3          3
select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper(             1           1          1
select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper(             1           3          3

8 rows selected

SQL>
SQL> SELECT NAME,VALUE FROM V$MYSTAT A,V$STATNAME B WHERE A.STATISTIC#=B.STATISTIC#
  2  AND NAME LIKE 'parse count%';

NAME                                                                  VALUE
---------------------------------------------------------------- ----------
parse count (total)                                                   42922
parse count (hard)                                                    40520
parse count (failures)                                                    2

SQL> insert into test values('1','1111111111');

1 row inserted

SQL> commit;

Commit complete

SQL> insert into test values('1','1111111111');

1 row inserted

SQL> commit;

Commit complete

SQL> select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper(sql_text) like '%TEST%';

SQL_TEXT                                                                         VERSION_COUNT PARSE_CALLS EXECUTIONS
-------------------------------------------------------------------------------- ------------- ----------- ----------
begin dbsnmp.mgmt_response.get_latest_curs(:a); end;                                         1           1          1
/* OracleOEM */  BEGIN   IF (:1 = 'READ WRITE') THEN     ----     -- For a read-             1           1          1
/* OracleOEM */  DECLARE         instance_number NUMBER;  latest_task_id NUMBER;             1           1          1
update sys.job$ set failures=0, this_date=null, flag=:1, last_date=:2,  next_dat             1           5          5
insert into test values('1','1111111111')                                                    1           5          5
DELETE FROM MGMT_DB_LATEST_HDM_FINDINGS WHERE TARGET_GUID = :B2 AND COLLECTION_T             2           3          3
select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper(             1           1          1
select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper(             1           4          4

8 rows selected

SQL>
SQL> SELECT NAME,VALUE FROM V$MYSTAT A,V$STATNAME B WHERE A.STATISTIC#=B.STATISTIC#
  2  AND NAME LIKE 'parse count%';

NAME                                                                  VALUE
---------------------------------------------------------------- ----------
parse count (total)                                                   42946
parse count (hard)                                                    40520
parse count (failures)                                                    2

SQL>


通过这个例子我们也就知道V$SQLAREA中的解析包含什么内容了。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29313086/viewspace-1694647/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: ORACLE触发器
下一篇: AIX下安装11GR2
请登录后发表评论 登录
全部评论

注册时间:2015-03-20

  • 博文量
    178
  • 访问量
    422836