U hebt een samengestelde index nodig op de intersectietabel:
ALTER TABLE instruments_tools ADD KEY (id_instrument, id_tool);
De volgorde van kolommen in die index is belangrijk!
Waar je op hoopt, is dat de joins beginnen met de instrumententabel en vervolgens het overeenkomende indexitem opzoeken in de samengestelde index op basis van id_instrument. Zodra het dat indexitem heeft gevonden, heeft het de bijbehorende id_tool gratis. Het hoeft dus helemaal niet de tabel instrument_tools te lezen, het hoeft alleen de index-ingang te lezen. Dat zou de opmerking "Using index" moeten geven in uw EXPLAIN voor de instrumenten_tools-tabel.
Dat zou moeten helpen, maar je kunt de temp table en filesort niet vermijden, omdat de kolommen waarop je groepeert en sorteert geen gebruik kunnen maken van een index.
U kunt proberen MySQL te voorkomen dat de tijdelijke tabel naar schijf wordt geschreven door het geheugen dat het voor tijdelijke tabellen kan gebruiken te vergroten:
mysql> SET GLOBAL tmp_table_size = 256*1024*1024; -- 256MB
mysql> SET GLOBAL max_heap_table_size = 256*1024*1024; -- 256MB
Dat cijfer is slechts een voorbeeld. Ik heb geen idee hoe groot het zou moeten zijn voor de tijdelijke tafel in jouw geval.