Java and Oracle expert Lukas Eder tweeted yesterday about a potential optimization that could be done when reviewing database SQL code.
This looks to be a logical thing to do. Why scan the table T twice to perform an update, when the same job could be done in a single pass. The benefits seem obvious:
- less I/O work
- less time the data is spent locked
- less risk of an error between the two operations
so don’t get me wrong – the consolidation is going to be a good thing in the majority of cases
And therein lies the rub – the “majority” of cases is the not the same as “all” cases, and that is why I don’t think a tool should ever automatically perform this change. I’d be cool with a tool making a recommendation but let’s see why you cannot just assume that the consolidation is correct.
Here’s our table with a single row and single business rule implement with a check constraint
SQL> create table t ( a int, b int ); Table created. SQL> alter table t add constraint chk check ( a < b ) ; Table altered. SQL> insert into t values (1,2); 1 row created. SQL> commit; Commit complete.
Now I’ll implement the application in the original “unoptimized” way:
SQL> update t set a = a + 1; update t set a = a + 1 * ERROR at line 1: ORA-02290: check constraint (MCDONAC.CHK) violated SQL> update t set b = b*2; 1 row updated.
You can see that the first update failed – it violated the check constraint. Of course, it is not definitively clear whether this should be the case based on the business requirements, because I haven’t elaborated on whether these two updates should be two transactions or a single transaction. The correctness is not really the point I’m trying to make here, but that if I now choose to consolidate the update, I end up with a different application behaviour.
I’ll roll back the change above, and repeat the experiment using the consolidate update:
SQL> roll; Rollback complete. SQL> update t set a = a + 1, b = b*2; 1 row updated.
This time the update completes successfully. If a tool had automatically done this, then I will get a different behaviour in my application. That might be a good thing..it might not be. I could eliminate the difference by implementing the constraint in a DEFERRED usage, but we’re starting to depart even further from the existing implementation of the application code, which means more scrutiny and more regression testing.
So by all means, explore opportunities to improve the performance of your SQL by re-arranging it, consolidating it, and aiming to get more done with less work. But be careful that you do not unknowingly change the way your application works when you do so.