Question

We have a system accessing an Oracle 11.g underlying database.

As part of the processing flow we have about sixty processes that keep polling the database looking for messages to process every 10 milliseconds.

Each processor has a corresponding row in a PROCESSORS table (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. If nothing to process it will update the MESSAGE_ID with a null value. With our current implementation it will still update the MESSAGE_ID to null even if the current value of the MESSAGE_ID is null. Updating a null with a null is what is happening in 90% of the time.

The polling process is happening inside a container managed transaction (CMT).

So we have lots of fake (null updated with null) updates followed by commits.

60 processors x 3600 seconds/hour x 100updates/second = 21600000 commits/hour

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.

Ideally we should change our system not to update the PROCESSORS entry if nothing changes and we will definitely do this. 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

Was it helpful?

Solution 2

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.

You may also want to watch out for some weird performance issues when updating the last column to 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.

OTHER TIPS

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. The link will help you understand more clearly.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top