views:

160

answers:

5

I am wondering about the performance of this index:

I have an "Invalid" varchar(1) column that has 2 values: NULL or 'Y' I have an index on (invalid), as well as (invalid, last_validated) Last_validated is a datetime (this is used for a unrelated SELECT query)

I am flagging a small amount of items (1-5%) of rows in the table with this as 'to be deleted'.
This is so when i

 DELETE FROM items WHERE invalid='Y'

it does not perform a full table scan for the invalid items.

A problem seems to be, the actual DELETE is quite slow now, possibly because all the indexes are being removed as they are deleted.

Would a bitmap index provide better performance for this? or perhaps no index at all?

+1  A: 

Index should be used, but DELETE can still take some time.

Have a look at the execution plan of the DELETE:

EXPLAIN PLAN FOR
  DELETE FROM items WHERE invalid='Y';

SELECT * FROM TABLE( dbms_xplan.display );

You could try using a Bitmap Index, but I doubt that it will have much impact on performance.


Using NULL as value is not a good idea. The query

SELECT something FROM items WHERE invalid IS NULL

would not be able to use your index, since it only contains not-null values.

Peter Lang
A: 

Two thoughts on this...

  1. Using NULL to express the opposite of 'Y' is possibly not a good idea. Null means *I don't know what this value is' or 'there is no meaningful answer to a question'. You should really use 'N' as the opposite of 'Y'. This would eliminate the problem of searching for valid items, because Oracle will not use the index on that column when it contains only non-null values.

  2. You may want to consider adding a CHECK CONSTRAINT on such a column to ensure that only legal values are entered.

Neither of these changes necessarily has any impact on DELETE performance however.

LBushkin
Logically, I agree with your point #1; in practice, however, there are *in some cases* significant performance benefits to representing uninteresting values as NULL in a column due to the fact Oracle does not store all-null rows in indexes - if the queries on that column are almost always only interested in the rare `Y` values, then having non-`Y` represented as NULL can have a huge impact on performance of queries, updates and deletes.
Jeffrey Kemp
+2  A: 

As Peter suggested, it's important to first verify that the index is being used for the delete. Bitmap indexes will invoke other locking for DML that could hurt overall performance.

Additional considerations:

  • are there unindexed foreign key references to this table from other tables?
  • are there triggers on this table that are performing other DML?
dpbradley
A: 

Drop the index on (invalid) and try both SELECT and DELETE. You already have an index on (invalid,last_validated). You should not be needing the index on invalid alone.Also approximately how many rows are there in this table ?

ap
The advantage of the index on `invalid` is that it will only contain rows where `invalid` is not null, and will thus be very fast to query. On the other hand, `(invalid, last_validated)` will contain an entry for each row that has either a non-null `invalid` or `last_validated`; if `last_validated` is mostly non-null the index will be quite large and therefore less suitable for this DELETE operation.
Jeffrey Kemp
A: 

I recommend:

  1. check how many records you expect the DELETE to affect (i.e. maybe there are more than you expect)
  2. if the number of rows that should be deleted is relatively small, check that the index on invalid is actually being used by the DELETE
  3. get a trace on the session to see what it is doing - it might be reading more blocks from disk than expected, or it might be waiting (e.g. record locking or latch contention)

Don't bother dropping or creating indexes until you have an idea of what actually is going on. You could make all kinds of changes, see an improvement (but not know why it improved), then months down the track the problem reoccurs or is even worse.

Jeffrey Kemp