What more can I do to optimize this query?
SELECT * FROM (SELECT `item`.itemID, COUNT(`votes`.itemID) AS `votes`, `item`.title, `item`.itemTypeID, `item`. submitDate, `item`.deleted, `item`.ItemCat, `item`.counter, `item`.userID, `users`.name, TIMESTAMPDIFF(minute,`submitDate`,NOW()) AS 'timeMin' , `myItems`.userID as userIDFav, `myItems`.deleted as myDeleted FROM (votes `votes` RIGHT OUTER JOIN item `item` ON (`votes`.itemID = `item`.itemID)) INNER JOIN users `users` ON (`users`.userID = `item`.userID) LEFT OUTER JOIN myItems `myItems` ON (`myItems`.itemID = `item`.itemID) WHERE (`item`.deleted = 0) GROUP BY `item`.itemID, `votes`.itemID, `item`.title, `item`.itemTypeID, `item`.submitDate, `item`.deleted, `item`.ItemCat, `item`.counter, `item`.userID, `users`.name, `myItems`.deleted, `myItems`.userID ORDER BY `item`.itemID DESC) as myTable where myTable.userIDFav = 3 or myTable.userIDFav is null limit 0, 20
I’m using MySQL
Thanks
Of course, as @theomega said, look at the execution plan.
But I’d also suggest to try and ‘clean up’ your statement. (I don’t know which one is faster – that depends on your table sizes.) Usually, I’d try to start with a clean statement and start optimizing from there. But typically, a clean statement makes it easier for the optimizer to come up with a good execution plan.
So here are some observations about your statement that might make things slow:
As far as I understand your SQL, this statement should do most of what yours is doing:
WHERE
Of course, this misses the info from the tables you outer joined, I’d suggest to try to add the required columns via a subselect:
This way, you can get rid of one outer join and the group by. The outer join is replaced by the subselect, so there is a trade-off which may be bad for the ‘cleaner’ statement.
Depending on the cardinality between item and myItems, you can do the same or you’d have to stick with the outer join (but no need to reintroduce the group by).
Hope this helps.