目前我的项目中有很多更新语句。我正在做的是传递一个列表 在DataAccess层中循环它并更新数据库
假设我有一个记录列表包含Comment,userID和ID ..我正在基于循环中的ID更新...有没有更好的方法来做...
我可以使用合并声明吗?它会提高性能吗?究竟是什么区别?
UPDATE RecordTable
SET
COMMENT=:COMMENT,
MODIFIEDDate = SYSTIMESTAMP,
UserID = :UserID
WHERE ID = :ID
答案 0 :(得分:4)
合并将更好然后更新,原因很简单,一次执行一行更新会导致大量不必要的上下文切换和索引/表访问。 Oracle在批量生产中运营得更好。
为了能够在此处使用合并声明,您必须使用ID
,COMMENT
和USERID
创建一个中间表。
只有在您可以执行合并
之后merge into RecordTable a using TEMP_recordtable b
on (a.id = b.id)
when matched then update set
a.COMMENT=b.COMMENT ,
a.MODIFIEDDate = SYSTIMESTAMP,
a.UserID = b.UserID
编辑:在没有临时表的情况下进行更新
演示表
SQL> create table m1 (id number , name varchar2(30) , updated date);
Table created.
SQL> insert into m1 values (1 , 'Haki', sysdate);
1 row created.
SQL> insert into m1 values (3 , 'Simon', sysdate);
1 row created.
SQL> commit;
SQL> select * from m1;
ID NAME UPDATED
---------- ------------------------------ -------------------
1 Haki 03/10/2013 09:39:37
3 Simon 03/10/2013 09:38:17
如果要在sql中使用集合,则需要在db
中声明它们SQL> create type rec as object (id number , name varchar2(10))
2 /
Type created.
SQL> create type rec_arr as table of rec;
2 /
Type created.
现在我们创建列表并将其合并到我们的表
SQL> ed
Wrote file afiedt.buf
1 declare
2 myarr rec_arr := rec_arr( rec (1 , 'Haki') , rec (2 , 'Raul'));
3 begin
4 merge into m1 using table(myarr) b on (m1.id = b.id)
5 when matched then update set
6 m1.name = b.name ,
7 m1.updated = sysdate
8 when not matched then insert (id , name , updated)
9 values (b.id , b.name , sysdate);
10* end;
SQL> /
PL/SQL procedure successfully completed.
SQL> select * from m1;
ID NAME UPDATED
---------- ------------------------------ -------------------
1 Haki 03/10/2013 09:40:16
3 Simon 03/10/2013 09:38:17
2 Raul 03/10/2013 09:40:16
3 rows selected.
如您所见,现有记录已更新,新记录已插入。
答案 1 :(得分:3)
您可以像执行合并一样轻松地批量执行更新。
将所需的更新值加载到全局临时表中,并确保在连接键上存在主要或唯一键约束,并且要更新表。您针对两个表的连接运行更新,类似于:
update (
select t.pk,
t.old_value,
s.new_value
from target_table t
join source_table s on (s.pk = t.some_column))
set old_value = new_value.
只要内联视图是“密钥保留”,更新就会像合并一样快。
http://docs.oracle.com/cd/E11882_01/server.112/e41084/statements_10008.htm
同样,您可以对密钥保留的视图或内嵌视图执行删除。
答案 2 :(得分:1)
正如其他人所指出的那样,上下文切换对性能来说太可怕了。但请记住,在减少上下文切换时,收益递减规律会很快发挥作用。一次填充10行会使它们减少90%,填充100行会使它们减少99%等等。为了获得大部分性能提升,您只需要组合相对较少的语句。
许多环境都有自动执行此操作的功能。例如PL / SQL forall
或JDBC批处理。如果那些不可用,你
可以通过在较大的语句中手动将数据集分组在一起来实现此目的。例如:
merge into RecordTable
using
(
select :id1 id, :comment1 comment, :userID1 userID from dual union all
select :id2 id, :comment2 comment, :userID2 userID from dual union all
...
select :id10 id, :comment10 comment, :userID10 userID from dual
) new_data
on RecordTable.id = new_data.id
when matched then update set
RecordTable.comment = new_data.comment,
RecordTable.modfifiedDate = systimestamp,
RecordTable.UserId = new_data.userID;
对于剩余的行,请使用null
作为ID,这些记录与任何内容都不匹配。
如果您的问题仅与merge
与update
有关,则最显着的性能差异是merge
可以支持散列连接,而update
则不能。但这不重要。