Generically, the places to focus on an Explain result are where:
- There are no possible keys to use
- There are a large number of rows returned
- Temporary tables and filesort are used
- Derived results from subqueries
Your indexes are stored in an efficient fashion, usually in order, whereas your data could be in any random order. Imagine a large book; you would need to read the whole thing to know that you've definitely found the information that you're looking for, whereas if you use the index you will be able to go straight to the term you need and won't need to look any further than the pages that it tells you to. So, where there's no possible key available, you can consider adding one. Personally I consider it good practice to have an index on any field that is used in a join, though in reality it may depend on the size of the table etc for whether there's any real-world benefit.
When you get 100 rows returned, and you then go further down and see another 100 rows returned (especially as a result of outer joins) you will multiply the number of original rows by the number of new rows. So 100x100 = 10,000 rows. When you've got 20,000 x 6 you will end up with 120,000 rows of data for the server to work through. Looking at your result, and if I'm not mistaken, you are returning a total of 2,387,775,606 rows. This is a HUGE amount of data that the server won't be able to keep in memory (depending on your configuration) so it will write it to a temporary table on disc and perform a filesort. Disc based operations are MUCH more costly than memory based, so it becomes much slower immediately. Large numbers of results, grouping and ordering generally always result in "Using temporary; Using filesort".
Lastly, and probably the primary reason for your particular problem (apologies for going the long way around) and the reason that you have so many rows returned as above, is that subqueries are just painfully slow in MySQL (usually). I don't believe that the jobs_locations join is doing you any favours at all, because as above, every time it appears to be returning 20,000 rows again. Is there any reason why you've used a subquery? Could you optimise it into a simple join? I would be focussing my attention there, personally
Bookmarks