[20120726]建立约束和使用绑定变量.txt

[20120726]建立约束和使用绑定变量.txt

昨天检查awr报表文件,发现:
select condition from cdef$ where rowid=:1
这条语句执行次数很高,因为查询的where条件使用rowid=:1,应该不会是用户的程序执行,而是某种递归的调用。

直接在google输入select condition from cdef$ where rowid=:1,发现如下链接:
http://jonathanlewis.wordpress.com/2006/12/14/constraints-inserts-and-bind/

原来我当时偷懒,直接使用toad导出insert语句导入别的数据库,这些insert语句没有使用绑定变量,而且正好这个表有个出生日期。我做了限制,限制出生日期必须大于'1900/1/1',还有其他2个约束,一共3个约束。

按照链接的介绍当没有绑定变量插入时,insert时每次都需要读取sys.cdef$的信息:

    Oracle doesn't keep long columns cached in the dictionary cache (rowcache) so every time it optimises a new statement
that uses a check constraint (and the condition column is a long column) it has to re-read the constraint definition from
the database – just as it does with the view definition when you optimise a statement that uses a view.
--我的测试对定义not null字段不进行再次检查。

自己在测试机器如下:

SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE    11.2.0.1.0      Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production

SQL> create table t ( id number check (id > 0), name varchar2(10) not null); 
SQL> column condition format a30
SQL> select obj#,condition from sys.cdef$ where obj# in (select object_id from dba_objects where wner=user and object_name='T');
      OBJ# CONDITION
---------- ------------------------------
    101266 "NAME" IS NOT NULL
    101266 id > 0

--可以发现存在两个约束在表T上。

2.测试:

alter system flush shared_pool;
SQL> select sql_text,executions from v$sql where sql_text like 'select condition from cdef$ where rowid=:1%';
no rows selected
begin 
 for i in 1..1000 loop 
  execute immediate 'insert into t values(' || i || ',''test'')'; 
 end loop; 
end; 
/
SQL> column sql_text format a60
SQL> select sql_text,executions from v$sql where sql_text like 'select condition from cdef$ where rowid=:1%';
SQL_TEXT                                                     EXECUTIONS
------------------------------------------------------------ ----------
select condition from cdef$ where rowid=:1                         1001

--可以发现select condition from cdef$ where rowid=:1执行了1001次。
--再次执行上面过程(注意我修改了循环的开始与结束值,如果不改,前面的insert sql语句已经在shared pool,

select condition from cdef$ where rowid=:1%的executions次数应该不存在变化)!
begin 
 for i in 1001..2000 loop 
  execute immediate 'insert into t values(' || i || ',''test'')'; 
 end loop; 
end; 
/
SQL> select sql_text,executions from v$sql where sql_text like 'select condition from cdef$ where rowid=:1%';
SQL_TEXT                                                     EXECUTIONS
------------------------------------------------------------ ----------
select condition from cdef$ where rowid=:1                         2001

--可以发现执行次数从1001=>2001.

3.可以发现如果insert的语句不使用绑定变量,在遇到有约束的字段就会执行1次select condition from cdef$ where rowid=:1%。
而对于像name varchar2(10) not null的约束仅仅访问1次。

再次修改约束条件,加入如下:

alter table t add constraint name_is_not_null check (name is not null);
SQL> select obj#,condition from sys.cdef$ where obj# in (select object_id from dba_objects where wner=user and object_name='T');
      OBJ# CONDITION
---------- ------------------------------
    101266 "NAME" IS NOT NULL
    101266 id > 0
    101266 name is not NULL
执行如下:
rollback;
begin 
 for i in 2001..3000 loop 
  execute immediate 'insert into t values(' || i || ',''test'')'; 
 end loop; 
end; 
/
SQL> select sql_text,executions from v$sql where sql_text like 'select condition from cdef$ where rowid=:1%';
SQL_TEXT                                                     EXECUTIONS
------------------------------------------------------------ ----------
select condition from cdef$ where rowid=:1                         4001

--可以发现执行次数从2001=>4001.增加了2000次。

4.改用绑定变量看看结果如何:

SQL> alter session set cursor_sharing = force ;
rollback;
begin 
 for i in 3001..4000 loop 
  execute immediate 'insert into t values(' || i || ',''test'')'; 
 end loop; 
end; 
/
SQL> select sql_text,executions from v$sql where sql_text like 'select condition from cdef$ where rowid=:1%';
SQL_TEXT                                                     EXECUTIONS
------------------------------------------------------------ ----------
select condition from cdef$ where rowid=:1                         4003

--可以发现执行次数从4001=>4003.仅仅增加2次。

总结:
又给使用绑定变量的使用找到一个好的理由,虽然遇到这种情况的不多,不过像insert语句,在表有主键的情况下,不可能一条语句执行多次!
一般在程序没有使用绑定的情况下,我的建议都是先修改有DML语句的地方,因为这些语句重复执行的可能性很小!

时间: 2024-07-30 10:52:20

[20120726]建立约束和使用绑定变量.txt的相关文章

[20150812]关于抓取绑定变量.txt

[20150812]关于抓取绑定变量.txt --通过视图v$sql_bind_capture以及DBA_HIST_SQLBIND可以抓取到sql语句的绑定变量.受到一些参数的限制,曾经写过一篇: [20130410]v$sql_bind_capture和隐含参数_bind_capture_area_size.txt http://blog.itpub.net/267265/viewspace-758175/ SCOTT@test> @ver1 PORT_STRING              

[20121102]PLSQL中的绑定变量.txt

[20121102]PLSQL中的绑定变量.txt     以前曾经遇到一个sql语句提交给开发,开发没有找到,最终确定是问题语句在PLSQL中,实际上PLSQL转化为大写, 加上自己没有注意.实际上SQL语句在PLSQL中,一些好像被"格式化一样",我举一个例子: 1.测试环境: SQL> select * from v$version where rownum BANNER ---------------------------------------------------

[20170929]& 代替冒号绑定变量.txt

[20170929]& 代替冒号绑定变量.txt --//我昨天看链接,http://orasql.org/2017/09/27/ampersand-instead-of-colon-for-bind-variables/ --//重复测试: SCOTT@book> @ &r/ver1 PORT_STRING                    VERSION        BANNER ------------------------------ -------------- -

[20130918]12c FETCH FIRST和绑定变量.txt

[20130918]12c FETCH FIRST和绑定变量.txt http://connormcdonald.wordpress.com/2013/09/11/12c-fetch-first/ 重复测试: @ver BANNER                                                                               CON_ID ------------------------------------------------

[20171019]绑定变量的分配长度7.txt

[20171019]绑定变量的分配长度7.txt --//如果绑定变量中字符串分配占用空间的长度变化,oracle会建立子光标. --//参考连接: http://blog.itpub.net/267265/viewspace-1993495/ --//oracle 可以通过一个10503事件设置大的缓存,测试看看: $ oerr ora 10503 10503, 00000, "enable user-specified graduated bind lengths" // *Cau

[20160313]绑定变量的分配长度4.txt

[20160313]绑定变量的分配长度4.txt --如果绑定变量中字符串分配占用空间的长度变化,oracle会建立子光标. --参考连接: http://blog.itpub.net/267265/viewspace-1993495/ http://blog.itpub.net/267265/viewspace-2024389/ http://blog.itpub.net/267265/viewspace-2050886/ --12c支持更长的字符串,顺便测试看看: --关于设置12c支持字串

[20160224]绑定变量的分配长度.txt

[20160224]绑定变量的分配长度.txt --如果绑定变量中字符串分配占用空间的长度变化,oracle会建立子光标. --昨天被别人问一个问题,通过例子来说明: 1.环境: SCOTT@book> @ &r/ver1 PORT_STRING                    VERSION        BANNER ------------------------------ -------------- -------------------------------------

[20161001]绑定变量的分配长度5.txt

[20161001]绑定变量的分配长度5.txt --如果绑定变量中字符串分配占用空间的长度变化,oracle会建立子光标. --一般如果绑定变量有多个字段在分配占用空间时长度变化,这样生成的子光标会增加. --我以前的测试字符串长度变化是32,32+96=128,32+96+1872=2000.也就是分4个段 1-32,33-128,129-2000,2001-4000. --相关链接: http://blog.itpub.net/267265/viewspace-1993495/ http:

[20160302]绑定变量的分配长度2.txt

[20160302]绑定变量的分配长度2.txt --如果绑定变量中字符串分配占用空间的长度变化,oracle会建立子光标. --参考连接: http://blog.itpub.net/267265/viewspace-1993495/ --oracle 可以通过一个10503事件设置大的缓存,测试看看: $ oerr ora 10503 10503, 00000, "enable user-specified graduated bind lengths" // *Cause: //