Smart Oracle

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

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

时常见到如下类似的SQL,根据primary key去做更新,且primary key还包括在被updated的column中。
[coolcode lang=”sql” linenum=”no”]
update emp set ID=:1,name=:2,birthdate=:3,description=:4 where ID=:5;
[/coolcode]
ID列自然是PK,且更新的时候ID的数值不会改变。(如果主键有更新的需求,则一般是表逻辑设计问题)

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

先建立测试环境
[coolcode lang=”sql” linenum=”no”]
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

[/coolcode]
无primary key更新的测试
[coolcode lang=”sql” linenum=”no”]
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’;
[/coolcode]

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

[coolcode lang=”sql” linenum=”no”]
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’;
[/coolcode]

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

[coolcode lang=”sql” linenum=”no”]
******************* 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)

[/coolcode]

从结果上看,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.