In a recent news tip on
SQL tuning with STATSPACK, I noted a potential performance enhancement
within Oracle where Oracle fails to check to see if an update is
superfluous.
An automated fix for superfluous updates?
A fix for this problem was add a WHERE clause predicate, and this
suggests the obvious question of whether Oracle could be enhanced to perform
automatic DML re-write, just as Oracle has been doing automatic SQL re-write
(i.e. MV, VPD).
Some of his blog commentators agreed that a fix to check and bypass
superfluous updates would be good, while others opposed such an enhancement.
The comments also suggests that some of his readers did not fully understand
his argument:
As you say, this check is dangerous staff [sic]
And
yes, an ‘off-switch’ would be a very good idea should Oracle introduce such
a smart update ‘feature’.
All this seems like the check was not
introduced (years ago…) because CPU was not so powerful and now it’s not
introduced because DISK are so fast…
David Aldridge also noted that the
superfluous update overhead is even worse with compressed tables, "in the
case of superfluous updates the effects really are severe in proportion to
the “superfluousness", and he notes his own
superfluous update test script and
results to show the overhead of Oracle superfluous updates on compressed
tables.
Everyone seems to dislike the overhead of superfluous
updates, but there is disagreement about how this "feature" might be fixed
and whether or not a automated fix might be dangerous. There are two
approaches to remedying superfluous updates, automatic DML re-write or a
block-level software solution. Let's take a closer look at this
fascinating issue.
- An optimizer-based fix for superfluous updates -
The Oracle optimizer already performs query rewrite for materialized
views, adds WHERE clause predicates for Virtual Private Database
(VPD) queries, and re-writes some subqueries. The Oracle SQL
optimizer could be enhanced to protect against the unnecessary overhead
of superfluous updates by negating the SET clause in the WHERE clause to
bypass rows that do not need to be updated.
- A database-level fix for superfluous updates - I
originally noted that the Oracle software might do a update validation
and bypass blocks that don't require updates. However, Lewis
argues that bypassing those data blocks that don't need changing might
somehow corrupt Oracle replication (Streams).
To any remote system, the supplemental logging files should look exactly
the same with either solution (changing the UPDATE syntax vs. an Oracle
Software change). In sum, we need to show that suppressing superfluous
updates, (either manually or via software enhancement) cannot corrupt any
replication mechanism, including Streams, Multi-master replication or Data
Guard.
Remember, just one test case is all that is needed to
show that a DML re-write approach would not always work. Any
software-side solution must be 100% safe, in all cases, on all releases, for
each and every obscure feature . . . .
Simple logic tells us that the supplemental logging cannot hurt anything
if Lewis' procedural solution (adding FLAG != 0 ) produces the exact same
redo as my proposed solutions;
1 - DML re-write - This would the exact same result as a
manual change to the update syntax.
2 - Change the Oracle executables
- If the kernel software is enhanced to bypass redo and block update when
there are no changes to the data blocks, we also get the exact same result
as a manual change to the update statement syntax.
However, just because the logging matches in this case does not mean that
Lewis' argument is without merit. I know how challenging it is to create
generalized decision rules for STATSPACK, (which I'm doing as part of the
team on www.statspackanalyzer.com)
and I know that even the most brilliant Oracle expert can misinterpret the
huge volumes of information within a STATSPACK report, especially when using
system-wide statistics to tune an individual job.
Laurent Schneider responds: (7/13/2007)
Take
care that rows with FLAG is null will not be updated in the second case (we
do not know if there is a not null constraint on FLAG).
I would write
update HISTORY
SET FLAG=0
WHERE
CLASS = 'X' and (FLAG != 0 or FLAG IS NULL);
one hundred rows updated.