2013-10-03 16 views
3

目前我有在我的项目很多UPDATE语句..What我做的是传递一个名单,然后在 数据访问层环路,并更新数据库更新vs Oracle合并以获得不是批量记录集的记录列表?性能?

让说,我有记录的列表包含注释,用户ID和ID ..我正在更新根据循环中的ID ...有没有更好的方式来做到这一点..

我可以使用合并报表吗?它会提高性能吗?究竟有什么区别?

UPDATE RecordTable 
SET 
COMMENT=:COMMENT, 
MODIFIEDDate = SYSTIMESTAMP, 
UserID = :UserID 
WHERE ID = :ID 
+0

听起来,目前尚不清楚,您的问题是在许多不同的地方保存相同的信息? – Ben

+0

@Ben它的工作一切正常...我只是问有没有更好的方式来更新表格的性能问题.. –

回答

4

合并会更好然后更新原因很简单,在一个时间执行一个更新的一行引起许多不必要的上下文切换和索引/表的访问。甲骨文的运营状况更好。

为了能够在这里使用合并语句,您必须创建一个中间表,其中包括ID,COMMENTUSERID

之后,才可以执行合并

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. 

正如你可以看到,现有的记录已被更新,新的记录被插入。

+0

感谢您的答案......但我没有2个表。我只是有一个列表集合和一张桌子...我可以合并吗??? –

+0

创建一个临时表。从您的应用程序插入到临时表中。然后,从temp合并到原始表中。 – haki

+0

明白了你的观点......但是否有可能不使用表格表,但是使用表格列表 –

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

同样可以进行删除针对键保存视图或内嵌视图。

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和这些记录将不匹配任何东西。

如果你的问题是只有约mergeupdate,最显著的性能差异是merge可以支持哈希联接和update不能。但这并不重要。

+0

去年开发批处理接口时,我也遇到了性能问题。我用同样的合并到声明中,我的问题得到解决。 – vamosrafa