簡體   English   中英

需要 MySQL 查詢優化幫助

[英]MySQL Query optimization help needed

我有以下查詢需要很長時間才能執行(大約 30 秒)。 有什么方法可以優化這個查詢還是我應該讓它?

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

您應該對用於連接的所有列都有索引。 更重要的是,你應該在db.vehicle上有一個索引:

db_vehicle(name, model, engine_type, id)

這應該用於where子句並加速查詢。

正如@Gordon Linoff 已經指出的那樣,您需要定義索引。 但是,還有一些事情需要進一步處理您的查詢。 定義好表格的順序當然更好,所以我們改變了這個

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

對此

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

這是一個更優雅的代碼,即使不能保證它實際上會比最初的更快。 然而,有了這個更好的順序,我們進入下一步。 where子句在join完成后執行,因此您將大量的多維記錄集加載到內存中並過濾掉行。 on條件執行得更早,所以下一步是修改where並將其條件遷移到on條件中,如下所示:

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 

這樣,不需要的記錄在join被過濾掉,減少了時間,因為它們不是全部加載到內存中然后過濾。 最后一步應該做的,當且僅當查詢仍然是緩慢的,因為它降低了代碼的可讀性:您可以修改join具有嚴重的過濾器(減少急劇的行數)或嚴重投影S(有許多大字段,但只需要其中的一小部分),以命名子選擇。 例子:

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 

最后的修改對l進行了預過濾,以確保只有少數記錄可以開始join

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM