You didn't say what performance you require. But you have a challenging query to satisfy.
Here's a suggestion for you. Do a so-called deferred join. As it is you're grabbing a lot of rows, ordering them, and then throwing out most of them. Let's order and throw out less stuff.
A subquery gets the id values you need to retrieve, like so.
SELECT id
FROM links
WHERE submit_after < CURDATE()
AND submitted < 4
ORDER BY ord
LIMIT 1438
This subquery can be optimized by a compound index, but (as others have pointed out) not perfectly.
Which of your WHERE
criteria is more selective? Which cuts down the number of resulting rows more aggressively? If it's the CURDATE criterion,
use this index: (submit_after, submitted, ord)
. If it's the submitted < 4
criterion, use this index. (submitted, submit_after, ord)
. These are called compound covering indexes.
Now, running that query gives you a list of ID values. All that has to be sorted is id
and ord
, a lesser workload than sorting the whole mess.
Edit. It's quite true that the number of rows to be sorted is the same in the subquery as in the main query. So, you might ask why this saves time. Simply because there are fewer, and shorter, columns, to sort in the subquery. Sorting has to manipulate a lot of data (EXPLAIN calls it "filesort"). Cutting down the volume of data to be manipulated can be very helpful.
To finish your job you use a JOIN like so:
SELECT a.id, a.url, a.submitted
FROM links AS a
JOIN (
SELECT id
FROM links
WHERE submit_after < CURDATE()
AND submitted < 4
ORDER BY ord
LIMIT 1438
) AS b ON a.id = b.id
ORDER BY a.ord
This retrieves a relatively much smaller number of rows from your main table once you have selected the ids you want. You end up sorting far less data: the ORDER BY this LIMIT that
pattern is wasteful because it discards a lot of already-sorted data.
Notice that you have to re-sort the main query. You may, upon experimenting, find that the main query is already in the right order without the second ORDER BY
. But you cannot rely on that behavior of the MySQL server.