Reputation: 1668
I need some help optimizing some queries for my database. I do understand the use of indexes in helping with joins and order by statements to help speed things up, but I was wondering if there were some techniques available to avoid using filesort and using temporary when I use the EXPLAIN command. Here's an example of what I am using.
SELECT a.id, DATE_FORMAT(a.submitted_at, '%d-%b-%Y') as submitted_at, a.user_id,
data1.*,
data2.name, data2.type,
u.first_name, u.last_name
FROM applications AS a
LEFT JOIN users AS u ON u.id = a.user_id
LEFT JOIN score_table AS data1 ON data1.applications_id = a.id
LEFT JOIN sections AS data2 ON data2.id = data1.section_id
WHERE category_id = [value] && submitted_at IS NOT NULL
ORDER BY data2.type
Again, indexes are being used properly in my queries like the one up above. If I take out the ORDER BY clause, then the query executes quickly from using the proper indexes. I understand that the order of the joins can affect the performance of the query. When I test using the ORDER BY on the users table, since it is the next table after the "const", it will only use "Using where, Using Filesort" on EXPLAIN. If I drop to any of the other tables, we get into the "Using Temporary" issue.
My question is: what would be the best way to optimize queries like this to run faster and in the best case scenario, avoid using filesort/temporary in EXPLAIN? I'm open to any possibilities :) I'm more or less interested in the theory on how to make queries like this perform better, than this exact query as I am having to perform more and more of these deep level ORDER BY queries in the database I'm working on.
--EDIT--
Here's the explain of the query above.....
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE a ref category_id,submitted_at category_id 4 const 49 Using where; Using temporary; Using filesort
1 SIMPLE u eq_ref PRIMARY PRIMARY 4 a.user_id 1
1 SIMPLE data1 ref app id app id 4 a.id 7
1 SIMPLE data2 eq_ref PRIMARY PRIMARY 4 data1.section_id 1
Upvotes: 1
Views: 1636
Reputation: 19979
Couple of things.
Are you sure you need to use 'LEFT JOIN'? Looking at the query it looks like you can get away with 'INNER JOIN' which will reduce the number of potential rows.
You didn't post your schema, but I assume that users.id, applications.user_id, score_table.applications_id, applications.id, sections.id and score_table.section_id are all ints? If they are non-ints I would strongly urge you to convert them. And if not primary keys, be sure they are indexed.
I wouldn't run any mysql level data formatting (i.e. DATE_FORMAT), as it will create some overhead during the query, rather I would format data like this at the app layer.
The ORDER BY forces MySQL to create a temp table in order to sort correctly, so be sure you absolutely need this functionality. If so, be sure that sections.type is indexed.
I would consider using a different alias naming convention. data1 and data2 are so abstract it's difficult to discern what they are actually referring to. I would suggest you use an abbreviated construct of the table you are aliasing, for example; applications becomes app (instead of a), score_table becomes score (instead of data1), etc.
Upvotes: 4