I have a query like this which takes a really long time to run. The table is around 4 million rows.
DELETE FROM TABLE WHERE value_was IS NULL OR value_was <= value_now;
I'm hoping I could create an index for (value_was, value_now) so I could do something like
DELETE FROM TABLE WHERE
ID1 IN (SELECT ID1 from TABLE where value_was IS NULL)
OR ID2 IN (SELECT ID2 FROM TABLE WHERE value_was <= value_now);
This table doesn't have primary key. It has two composite keys. And I guess I cannot use the same table in subquery, but how do I improve the performance of the first query?
Thanks very much any suggestion would be much appreciated.
Best Answer
Unfortunately, MySQL is quite notorious for subquery issues, particularly with non-SELECTs queries. I once addressed this back on
Feb 22, 2011
: Problem with MySQL subqueryIn that old post I found documentation on how MySQL handles subqueries. I have tried to keep up with this because I last edited my post on
Oct 20, 2012
with the latest documentation.In brief, subquery optimization may have rows disappear intermittently for the sake of getting the EXPLAIN plan figured out. You can read the documentation and learn about it if you can your wrap head around it (not going through that again).
Now for your question...
The most sensible approach, no JOINs, no sub-SELECTs, is the following:
Will you look at that. It's your query from the question. Why suggest your original idea ?
It is a full table scan IN ONE PASS. Any other approach can potentially double the work (or triple it if you try to get indexes involved this late in the game). Running it this way also delays the need to defragment the table.
If you want to delete and defragment, here are two options.
OPTION #1
MyISAM
InnoDB
OPTION #2
CAVEAT
Before you do anything, run this count
@DeletePct
is the Percentage of the Table that will be deleted if you run theDELETE
.If the Percentage is too low for you, then
DELETE FROM
TABLEWHERE value_was IS NULL OR value_was <= value_now;
is all you need. Defragmentation can wait. Otherwise, you may choose one of the options or live with the table's row fragmentation.On a side note, if you wish employ the use of indexes, please so after defragmenting the table.