简体   繁体   English

在不真正更改数据的情况下发出多个提交时的性能影响

[英]Performance impact when issuing multiple commits without really changing the data

We have a system accessing an Oracle 11.g underlying database. 我们有一个系统可以访问Oracle 11.g基础数据库。

As part of the processing flow we have about sixty processes that keep polling the database looking for messages to process every 10 milliseconds. 作为处理流程的一部分,我们大约有60个进程一直在轮询数据库,以查找每10毫秒要处理的消息。

Each processor has a corresponding row in a PROCESSORS table (PROCESSOR_ID NUMBER, MESSAGGE_ID NUMBER) 每个处理器在PROCESSORS表中都有对应的行(PROCESSOR_ID NUMBER,MESSAGGE_ID NUMBER)

If a message to process is found for a given processor it will update the MESSAGE_ID column for that processor. 如果找到给定处理器要处理的消息,它将更新该处理器的MESSAGE_ID列。 If nothing to process it will update the MESSAGE_ID with a null value. 如果没有任何处理,它将使用空值更新MESSAGE_ID。 With our current implementation it will still update the MESSAGE_ID to null even if the current value of the MESSAGE_ID is null. 在我们当前的实现中,即使MESSAGE_ID的当前值为null,它仍会将MESSAGE_ID更新为null。 Updating a null with a null is what is happening in 90% of the time. 在90%的时间内,用null更新null。

The polling process is happening inside a container managed transaction (CMT). 轮询过程在容器管理的事务(CMT)中进行。

So we have lots of fake (null updated with null) updates followed by commits. 因此,我们有很多伪造的(null更新为null)更新,然后是提交。

60 processors x 3600 seconds/hour x 100updates/second = 21600000 commits/hour 60个处理器x 3600秒/小时x 100次更新/秒= 21600000提交/小时

In reality they are about 16 millions transactions/hour because when something is found for processing it will take more time before looking for work again. 实际上,它们每小时大约有1600万笔交易,因为找到要处理的东西后,将需要更多的时间才能再次寻找工作。

Ideally we should change our system not to update the PROCESSORS entry if nothing changes and we will definitely do this. 理想情况下,如果没有任何变化,我们应该更改系统以不更新PROCESSORS条目,我们一定会这样做。 However the transactional behaviour of the polling process is outside our control (the container and a third party workflow product does it for us) so it will still be lots of commits regardless we updating that record or not. 但是,轮询过程的事务行为超出了我们的控制范围(容器和第三方工作流产品为我们完成了任务),因此无论我们是否更新该记录,仍然会有很多提交。

So my question would be: would you think that this “update nothing” then commit will have a performance impact on the system and if yes would you think that removing the “update nothing” will improve it. 所以我的问题是:您是否认为此“不更新”然后提交会对系统性能产生影响;如果是,您是否会认为删除“不更新”会改进它。

The reason for my question is that just days before the release, as part of our performance runs we found out that the system is running OK for about ten hours and then suddenly out of nowhere its starts performing very poorly. 我提出这个问题的原因是,在发布前几天,作为性能运行的一部分,我们发现系统正常运行了大约十个小时,然后突然突然出现运行异常的情况。

Thanks in advance 提前致谢

Definitely commits are overhead to the database, A commit consumes additional resource and runs slower. 无疑,提交是数据库的开销,一个提交会消耗额外的资源,并且运行速度较慢。 In certain cases it may cause data integrity issue as well. 在某些情况下,它也可能导致数据完整性问题。

In fact, you should fire a commit only when your transaction is complete, when there is no transaction at all, why going for giving extra burden to the database? 实际上,您应该仅在事务完成时,根本没有事务时才触发提交,为什么还要给数据库增加负担呢?

Even more, you can explore much more in a very good article by Tom Kyte. 甚至,您可以在Tom Kyte的一篇非常好的文章中探索更多内容 The link will help you understand more clearly. 该链接将帮助您更清楚地了解。

Removing the "update nothing" will significantly improve performance. 删除“什么也不更新”将大大提高性能。 Updating a column to the same value is just as expensive as updating to a different value. 将列更新为相同的值与更新为不同的值一样昂贵。 The simple test case below shows a significant improvement after removing the unnecessary update. 下面的简单测试案例显示了删除不必要的更新后的重大改进。

drop table processors;

create table PROCESSORS
(
    PROCESSOR_ID NUMBER primary key,
    MESSAGE_ID NUMBER
);

insert into processors
select level, null
from dual connect by level <= 100;

commit;

begin
    for i in 1 .. 100000 loop
        update processors set message_id = null where processor_id = 1;
        commit;
    end loop;
end;
/

begin
    for i in 1 .. 100000 loop
        --update processors set message_id = null where processor_id = 1;
        commit;
    end loop;
end;
/

On my desktop removing the update improved run time from 8.5 seconds to 1.3 seconds. 在我的桌面上,删除update将运行时间从8.5秒缩短到1.3秒。

You may also want to watch out for some weird performance issues when updating the last column to null . 将最后一列更新为null时,您可能还需要注意一些奇怪的性能问题 After removing the meaningless updates it might be worth switching the column order so that the updated column is first, to avoid heap block compress waits. 删除无意义的更新后,可能有必要切换列顺序,以使更新的列位于第一位,以避免堆块压缩等待。 But I wouldn't optimize for that problem until you know it's happening. 但是,除非您知道它正在发生,否则我不会针对该问题进行优化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM