Index maintained on update if no change?
If an update statement changes an indexed the column, any index using that column must be maintained. However, if the "new" value of the indexed column is the same as the current value (no net change), is there any wasted time trying to maintain an index that won't really change?
A popular application has the peculiar habit of including the keys in both the Set and Where clause when using the "preferred" built-in method for issuing individual updates. Time wasted maintaining indexs with those columns could add up when processing tens or hundreds of thousands of rows. There is an option to issue the actual SQL instead, so it seems worth exploring.
we do not maintain indexes if the data values do not change.
That can be observed by doing an update of a column from one value to another, measuring the db block gets (current mode, update style gets) and then modifying the column to its current value, back and forth.
eg:
ops$tkyte%ORA10GR2> create table t 2 as 3 select 1 x from all_objects; Table created. ops$tkyte%ORA10GR2> create index t_idx on t(x); Index created. ops$tkyte%ORA10GR2> update t set x = 2; 50388 rows updated. ops$tkyte%ORA10GR2> commit; Commit complete. ops$tkyte%ORA10GR2> update t set x = 1; 50388 rows updated. ops$tkyte%ORA10GR2> commit; Commit complete. ops$tkyte%ORA10GR2> set autotrace traceonly statistics; ops$tkyte%ORA10GR2> update t set x = 2; 50388 rows updated. Statistics ---------------------------------------------------------- 255500 db block gets 176 consistent gets 34191460 redo size ops$tkyte%ORA10GR2> commit; Commit complete. ops$tkyte%ORA10GR2> update t set x = 2; 50388 rows updated. Statistics ---------------------------------------------------------- 51556 db block gets 12535632 redo size 50388 rows processed ops$tkyte%ORA10GR2> commit; Commit complete. ops$tkyte%ORA10GR2> update t set x = 2; 50388 rows updated. Statistics ---------------------------------------------------------- 51688 db block gets 12541488 redo size 50388 rows processed ops$tkyte%ORA10GR2> commit; Commit complete. ops$tkyte%ORA10GR2> update t set x = 1; 50388 rows updated. Statistics ---------------------------------------------------------- 255415 db block gets 34187164 redo size 50388 rows processed ops$tkyte%ORA10GR2> commit; Commit complete. ops$tkyte%ORA10GR2> update t set x = 1; 50388 rows updated. Statistics ---------------------------------------------------------- 51544 db block gets 12536032 redo size 50388 rows processed ops$tkyte%ORA10GR2> commit; Commit complete. ops$tkyte%ORA10GR2> update t set x = 1; 50388 rows updated. ops$tkyte%ORA10GR2> create table t 2 as 3 select 1 x from all_objects; Table created. ops$tkyte%ORA10GR2> create index t_idx on t(x); Index created. ops$tkyte%ORA10GR2> update t set x = 2; 50388 rows updated. ops$tkyte%ORA10GR2> commit; Commit complete. ops$tkyte%ORA10GR2> update t set x = 1; 50388 rows updated. ops$tkyte%ORA10GR2> commit; Commit complete. ops$tkyte%ORA10GR2> set autotrace traceonly statistics; ops$tkyte%ORA10GR2> update t set x = 2; 50388 rows updated. Statistics ---------------------------------------------------------- 255500 db block gets 176 consistent gets 34191460 redo size ops$tkyte%ORA10GR2> commit; Commit complete. ops$tkyte%ORA10GR2> update t set x = 2; 50388 rows updated. Statistics ---------------------------------------------------------- 51556 db block gets 12535632 redo size 50388 rows processed ops$tkyte%ORA10GR2> commit; Commit complete. ops$tkyte%ORA10GR2> update t set x = 2; 50388 rows updated. Statistics ---------------------------------------------------------- 51688 db block gets 12541488 redo size 50388 rows processed ops$tkyte%ORA10GR2> commit; Commit complete. ops$tkyte%ORA10GR2> update t set x = 1; 50388 rows updated. Statistics ---------------------------------------------------------- 255415 db block gets 34187164 redo size 50388 rows processed ops$tkyte%ORA10GR2> commit; Commit complete. ops$tkyte%ORA10GR2> update t set x = 1; 50388 rows updated. Statistics ---------------------------------------------------------- 51544 db block gets 12536032 redo size 50388 rows processed ops$tkyte%ORA10GR2> commit; Commit complete. ops$tkyte%ORA10GR2> update t set x = 1; 50388 rows updated.
see the radical decrease in db block (current mode, update mode) gets and redo size?
we skipped the index maintenance