I have an SQL query with a nested join:
SELECT rh.host, rh.report, COUNT(results.id), COUNT(results_2.id), COUNT(results_3.id), COUNT(results_4.id)
FROM report_hosts rh
INNER JOIN report_results rr ON rh.report = rr.report
LEFT OUTER JOIN results ON rr.result = results.id AND results.type = 'Hole' AND results.host = rh.host
LEFT OUTER JOIN results results_2 ON rr.result = results_2.id AND results_2.type = 'Warning' AND results_2.host = rh.host
LEFT OUTER JOIN results results_3 ON rr.result = results_3.id AND results_3.type = 'Note' AND results_3.host = rh.host
LEFT OUTER JOIN results results_4 ON rr.result = results_4.id AND results_4.type = 'Log' AND results_4.host = rh.host
GROUP BY rh.host
The query as-is takes about 5sec with 99.7% copying to temp table. An EXPLAIN of the full query shows as:
+----+-------------+-----------+--------+---------------+---------+---------+-------------------+------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+--------+---------------+---------+---------+-------------------+------+---------------------------------+
| 1 | SIMPLE | rr | ALL | report | NULL | NULL | NULL | 3139 | Using temporary; Using filesort |
| 1 | SIMPLE | rh | ref | report | report | 5 | openvas.rr.report | 167 | Using where |
| 1 | SIMPLE | results | eq_ref | PRIMARY,type | PRIMARY | 4 | openvas.rr.result | 1 | |
| 1 | SIMPLE | results_2 | eq_ref | PRIMARY,type | PRIMARY | 4 | openvas.rr.result | 1 | |
| 1 | SIMPLE | results_3 | eq_ref | PRIMARY,type | PRIMARY | 4 | openvas.rr.result | 1 | |
| 1 | SIMPLE | results_4 | eq_ref | PRIMARY,type | PRIMARY | 4 | openvas.rr.result | 1 | |
+----+-------------+-----------+--------+---------------+---------+---------+-------------------+------+---------------------------------+
When I remove the LEFT JOINs, the query executes in about 1s, each LEFT JOIN adds about one additional second execution time.
My question:
Can anyone explain, why the copy to temp table task of one join takes longer if there are more LEFT JOINs? Is MySQL copying the temp table several times for each JOIN?
How can I avoid this? Am I missing an index?
What I intend to accomplish: I have a table with scanning results of several hosts. Each result is classified in types ( "Hole", "Warning", "Note" or "Log"). I want to select each host and the corresponding amount of Holes, Warnings, Notes and Logs. As a "restriction" I have the fact, that not each host has each type of results.