Smart Oracle

December 1st, 2007 | Categories: Boring | Tags:

在作记录更新的时候,有些由数据库开发工具生成的update语句,会去更新所有的字段,而不管这个字段是否有实际的内容改动。这样带来额外的over head.

时常见到如下类似的SQL,根据primary key去做更新,且primary key还包括在被updated的column中。

update emp set ID=:1,name=:2,birthdate=:3,description=:4 where ID=:5;

ID列自然是PK,且更新的时候ID的数值不会改变。(如果主键有更新的需求,则一般是表逻辑设计问题)

那么update语句中,有无这个主键的更新,会有什么性能影响哪?

先建立测试环境

SQL> drop table test;
Table dropped.
 
SQL> create table test as select * from dba_objects;
Table created.
 
SQL> delete from test where owner is null or object_id is null or object_type is null;
21 rows deleted.
 
SQL> alter table test add primary key(owner,object_id,object_type);
Table altered.
 
SQL>
SQL> analyze table test compute statistics;
Table analyzed.
 
SQL> select count(*) from test;
 
COUNT(*)
--------
--
     12126

 
SQL> select /*+ full(a) */ count(*) from test a;
 
COUNT(*)
--------
--
     12126

无primary key更新的测试

SQL> select name,value from v$mystat m,v$statname s where m.STATISTIC#=s.STATISTIC# and name='redo size';
SQL> alter session set sql_trace=true;
Session altered.
 
SQL> begin
 
2  for i in (select owner,object_type,object_id from dba_objects) loop
 
3  update test set  SUBOBJECT_NAME='S' ,TEMPORARY='S',GENERATED='S',
 
4    CREATED=sysdate  where owner=i.owner and object_id=i.object_id and object_type=i.object_type;
 
5  end loop;
 
6  commit;
 
7  end;
 
8  /
 
PL/SQL procedure successfully completed.
 
SQL> alter session set sql_trace=false;
Session altered.
SQL> select name,value from v$mystat m,v$statname s where m.STATISTIC#=s.STATISTIC# and name='redo size';

包括primary key更新的测试,但实际primary key的数值不变

SQL> select name,value from v$mystat m,v$statname s where m.STATISTIC#=s.STATISTIC# and name='redo size';
SQL> alter session set sql_trace=true;
Session altered.
 
SQL> begin
 
2  for i in (select owner,object_type,object_id from dba_objects) loop
 
3  update test set  owner=i.owner,object_id=i.object_id,object_type=i.object_type,
 
4     SUBOBJECT_NAME='S' ,TEMPORARY='S',GENERATED='S',
 
5    CREATED=sysdate  where owner=i.owner and object_id=i.object_id and object_type=i.object_type;
 
6  end loop;
 
7  commit;
 
8  end;
 
9  /
PL/SQL procedure successfully completed.
 
SQL> alter session set sql_trace=false;
SQL> select name,value from v$mystat m,v$statname s where m.STATISTIC#=s.STATISTIC# and name='redo size';

主要观察两个更新语句在logical reads, cpu, redo size上的不同。

******************* PK gets updated in update statement***********************
 
UPDATE TEST SET OWNER=:B6 ,OBJECT_ID=:B5 ,OBJECT_TYPE=:B4 , SUBOBJECT_NAME=
 
'S' ,TEMPORARY='S',GENERATED='S', CREATED=SYSDATE
WHERE
 
OWNER=:B3 AND OBJECT_ID=:B2 AND OBJECT_TYPE=:B1
 
call     count       cpu    elapsed       disk      query    current        rows
-----
-- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute  12148      2.02       2.06          0      24254      12617       12126
Fetch        0      0.00       0.00          0          0          0           0
-----
-- ------  -------- ---------- ---------- ---------- ----------  ----------
total    12149      2.02       2.06          0      24254      12617       12126
 
Rows     Row Source Operation
-----
--  ---------------------------------------------------
 
12126  UPDATE  TEST (cr=24254 pr=0 pw=0 time=1327587 us) redo size=4461084
 
12126   INDEX UNIQUE SCAN SYS_C0044327 (cr=24254 pr=0 pw=0 time=206653 us)(object id 444952)
 
*****************************
good update statement*********************************
 
UPDATE TEST SET SUBOBJECT_NAME='S' ,TEMPORARY='S',GENERATED='S', CREATED=
 
SYSDATE
WHERE
 
OWNER=:B3 AND OBJECT_ID=:B2 AND OBJECT_TYPE=:B1
 
call     count       cpu    elapsed       disk      query    current        rows
-----
-- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute  12148      1.75       1.84          0      24254      12519       12126
Fetch        0      0.00       0.00          0          0          0           0
-----
-- ------  -------- ---------- ---------- ---------- ----------  ----------
total    12149      1.75       1.84          0      24254      12519       12126
 
Rows     Row Source Operation
-----
--  ---------------------------------------------------
 
12126  UPDATE  TEST (cr=24254 pr=0 pw=0 time=1158086 us)  redo size=3704140
 
12126   INDEX UNIQUE SCAN SYS_C0044325 (cr=24254 pr=0 pw=0 time=209671 us) (object id 444948)

从结果上看,logical reads基本一样。redo size 和 cpu 使用,略有不同。这说明,当PK索引更新数值一样的时候,oracle不会去做PK索引的实际更新,有够Smart。但仍然要在redo size和cpu上多些overhead,对于关键的应用,仍然要有良好的编码习惯。

Del.icio.us Google书签 Digg Live Bookmark Technorati Furl Yahoo书签 Facebook 百度搜藏 新浪 ViVi 365Key 网摘 天极网摘 和讯网摘 博拉网 POCO 网摘 饭否 QQ 书签 Digbuzz 我挖网 Mister Wong
No comments yet.