As @Gordon Linoff already pointed out, you need to define indexes. However, there are some things to do further with your query. It is certainly better to define well the order of your tables, so we change this
SELECT l.Name, l.Model, l.Engine_Type, m.ID, g.Name
FROM db.vehicle_part k
JOIN db.vehicle l ON k.ID_Vehicle = l.ID
JOIN db.part m ON k.ID_Part = m.ID
JOIN db.part_generic_part b ON b.ID_Part = m.ID
JOIN db.generic_part c ON c.ID = b.ID_Generic_part
JOIN db.generic_part_name d ON c.ID = d.ID_Generic_Part
JOIN db.part_category_generic_part e ON c.ID = e.ID_generic_part
JOIN db.part_category f ON e.ID_category = f.ID
JOIN db.part_category_name g ON f.ID = g.ID_Part_Category
JOIN db.lang h ON g.ID_Lang = h.ID
WHERE l.Name = 'BMW' AND l.Model = '3 (E30)' AND l.Engine_Type= '316 i' AND g.ID_Lang =2
to this
SELECT l.Name, l.Model, l.Engine_Type, m.ID, g.Name
FROM db.vehicle_part k
JOIN db.vehicle l ON k.ID_Vehicle = l.ID
JOIN db.part m ON k.ID_Part = m.ID
JOIN db.part_generic_part b ON b.ID_Part = m.ID
JOIN db.generic_part c ON c.ID = b.ID_Generic_part
JOIN db.part_category_generic_part e ON c.ID = e.ID_generic_part
JOIN db.part_category f ON e.ID_category = f.ID
JOIN db.part_category_name g ON f.ID = g.ID_Part_Category
JOIN db.lang h ON g.ID_Lang = h.ID
JOIN db.generic_part_name d ON c.ID = d.ID_Generic_Part
WHERE l.Name = 'BMW' AND l.Model = '3 (E30)' AND l.Engine_Type= '316 i' AND g.ID_Lang =2
This is a more elegant code, even though there is no guarantee that it will actually be quicker than the initial one. However, with this better order, we go to the next step. The where
clause is executed AFTER the join
is completed, so you have a large, multi-dimensional set of records loaded into memory and you filter the rows out. The on
condition executes earlier, so the next step is to modify the where
and migrate its condition into on
conditions, like this:
SELECT l.Name, l.Model, l.Engine_Type, m.ID, g.Name
FROM db.vehicle_part k
JOIN db.vehicle l ON k.ID_Vehicle = l.ID AND l.Name = 'BMW' AND l.Model = '3 (E30)' AND l.Engine_Type= '316 i'
JOIN db.part m ON k.ID_Part = m.ID
JOIN db.part_generic_part b ON b.ID_Part = m.ID
JOIN db.generic_part c ON c.ID = b.ID_Generic_part
JOIN db.part_category_generic_part e ON c.ID = e.ID_generic_part
JOIN db.part_category f ON e.ID_category = f.ID
JOIN db.part_category_name g ON f.ID = g.ID_Part_Category and g.ID_Lang =2
JOIN db.lang h ON g.ID_Lang = h.ID
JOIN db.generic_part_name d ON c.ID = d.ID_Generic_Part
This way, unneeded records are filtered out while join
ing, reducing time, since they are not all loaded into memory and then filtered. The final step should be done if and only if the query is still slow, since it reduces the readability of the code: you can modify the join
s having a severe filter (reducing drastically the number of rows) or a severe projection (having many large fields, but needed only a small subset of that), to named subselects. Example:
SELECT 'BMW', '3 (E30)', '316 i', m.ID, g.Name
from (select temp.ID from db.vehicle temp where temp.Name = 'BMW' AND temp.Model = '3 (E30)' AND temp.Engine_Type= '316 i') l
JOIN db.vehicle_part k on l.ID = k.ID_VEHICLE
JOIN db.part m ON k.ID_Part = m.ID
JOIN db.part_generic_part b ON b.ID_Part = m.ID
JOIN db.generic_part c ON c.ID = b.ID_Generic_part
JOIN db.part_category_generic_part e ON c.ID = e.ID_generic_part
JOIN db.part_category f ON e.ID_category = f.ID
JOIN db.part_category_name g ON f.ID = g.ID_Part_Category and g.ID_Lang =2
JOIN db.lang h ON g.ID_Lang = h.ID
JOIN db.generic_part_name d ON c.ID = d.ID_Generic_Part
This final modification prefilters l
to make sure there are only a handful of records to start the join
with.