[英]How to speed up a complex SQL query with JOINs
我正在使用以下查詢,正如您通過下面的結果所看到的,返回結果需要2個多小時。 我很想知道如何加快速度 - 我相信我已經正確地構建了索引但是仍然需要花費大量的時間來返回這些數據。
EXPLAIN SELECT Import_Values.base_vehicle_id,
Import_Values.qty,
Import_Values.part_type_id,
Import_Values.part_id,
Import_Values.position_id,
Import_Values.note,
Parts.partterminologyname,
BaseVehicle.YearID,
Make.MakeName,
Model.modelname,
SubModel.SubModelName,
EngineDesignation.EngineDesignationName,
EngineVIN.EngineVINName,
EngineBase.Liter,
EngineBase.CC,
EngineBase.CID,
EngineBase.Cylinders,
EngineBase.BlockType,
EngineBase.EngBoreIn,
EngineBase.EngBoreMetric,
EngineBase.EngStrokeIn,
EngineBase.EngStrokeMetric,
FuelDeliveryType.FuelDeliveryTypeName,
FuelDeliverySubType.FuelDeliverySubTypeName,
FuelSystemControlType.FuelSystemControlTypeName,
FuelSystemDesign.FuelSystemDesignName,
Aspiration.AspirationName,
CylinderHeadType.CylinderHeadTypeName,
FuelType.FuelTypeName,
IgnitionSystemType.IgnitionSystemTypeName,
Mfr.MfrName,
EngineVersion.EngineVersion,
Valves.ValvesPerEngine,
BedLength.BedLength,
BedLength.BedLengthMetric,
BedType.BedTypeName
FROM
Import_Values
INNER JOIN BaseVehicle
ON Import_Values.base_vehicle_id=BaseVehicle.BaseVehicleID
INNER JOIN Parts
ON Import_Values.part_type_id=Parts.PartTerminologyID
INNER JOIN Make
ON BaseVehicle.MakeID=Make.MakeID
INNER JOIN Model
ON BaseVehicle.ModelID=Model.ModelID
INNER JOIN Vehicle
ON Import_Values.base_vehicle_id=Vehicle.BaseVehicleID
INNER JOIN SubModel
ON Vehicle.SubModelID=SubModel.SubModelID
INNER JOIN VehicleConfig
ON Vehicle.VehicleID=VehicleConfig.VehicleID
INNER JOIN EngineConfig
ON VehicleConfig.EngineConfigID=EngineConfig.EngineConfigID
INNER JOIN EngineDesignation
ON EngineConfig.EngineDesignationID=EngineDesignation.EngineDesignationID
INNER JOIN EngineVIN
ON EngineConfig.EngineVINID=EngineVIN.EngineVINID
INNER JOIN EngineBase
ON EngineConfig.EngineBaseID=EngineBase.EngineBaseID
INNER JOIN FuelDeliveryConfig
ON EngineConfig.FuelDeliveryConfigID=FuelDeliveryConfig.FuelDeliveryConfigID
INNER JOIN FuelDeliveryType
ON FuelDeliveryConfig.FuelDeliveryTypeID=FuelDeliveryType.FuelDeliveryTypeID
INNER JOIN FuelDeliverySubType
ON FuelDeliveryConfig.FuelDeliverySubTypeID=FuelDeliverySubType.FuelDeliverySubTypeID
INNER JOIN FuelSystemControlType
ON FuelDeliveryConfig.FuelSystemControlTypeID=FuelSystemControlType.FuelSystemControlTypeID
INNER JOIN FuelSystemDesign
ON FuelDeliveryConfig.FuelSystemDesignID=FuelSystemDesign.FuelSystemDesignID
INNER JOIN Aspiration
ON EngineConfig.AspirationID=Aspiration.AspirationID
INNER JOIN CylinderHeadType
ON EngineConfig.CylinderHeadTypeID=CylinderHeadType.CylinderHeadTypeID
INNER JOIN FuelType
ON EngineConfig.FuelTypeID=FuelType.FuelTypeID
INNER JOIN IgnitionSystemType
ON EngineConfig.IgnitionSystemTypeID=IgnitionSystemType.IgnitionSystemTypeID
INNER JOIN Mfr
ON EngineConfig.EngineMfrID=Mfr.MfrID
INNER JOIN EngineVersion
ON EngineConfig.EngineVersionID=EngineVersion.EngineVersionID
INNER JOIN Valves
ON EngineConfig.ValvesID=Valves.Valvesid
INNER JOIN BedConfig
ON VehicleConfig.BedConfigID=BedConfig.BedConfigID
INNER JOIN BedLength
ON BedConfig.BedLengthID=BedLength.BedLengthID
INNER JOIN BedType
ON BedConfig.BedTypeID=BedType.BedTypeID
結果......
+----+-------------+-----------------------+--------+-----------------------+---------+---------+-----------------------------------------------------------------+--------+-------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------------------+--------+-----------------------+---------+---------+-----------------------------------------------------------------+--------+-------------------+
| 1 | SIMPLE | VehicleConfig | ALL | NULL | NULL | NULL | NULL | 171375 | |
| 1 | SIMPLE | Import_Values | ALL | base_vehicle_id | NULL | NULL | NULL | 18933 | Using join buffer |
| 1 | SIMPLE | BedConfig | eq_ref | PRIMARY | PRIMARY | 4 | icarcare_importfeeds.VehicleConfig.BedConfigID | 1 | |
| 1 | SIMPLE | BedType | eq_ref | PRIMARY | PRIMARY | 4 | icarcare_importfeeds.BedConfig.BedTypeID | 1 | |
| 1 | SIMPLE | BedLength | eq_ref | PRIMARY | PRIMARY | 4 | icarcare_importfeeds.BedConfig.BedLengthID | 1 | |
| 1 | SIMPLE | EngineConfig | eq_ref | PRIMARY,EngineBaseID | PRIMARY | 4 | icarcare_importfeeds.VehicleConfig.EngineConfigID | 1 | |
| 1 | SIMPLE | FuelType | eq_ref | PRIMARY | PRIMARY | 4 | icarcare_importfeeds.EngineConfig.FuelTypeID | 1 | |
| 1 | SIMPLE | Valves | eq_ref | PRIMARY | PRIMARY | 4 | icarcare_importfeeds.EngineConfig.ValvesID | 1 | |
| 1 | SIMPLE | EngineVIN | eq_ref | PRIMARY | PRIMARY | 4 | icarcare_importfeeds.EngineConfig.EngineVINID | 1 | |
| 1 | SIMPLE | EngineVersion | eq_ref | PRIMARY | PRIMARY | 4 | icarcare_importfeeds.EngineConfig.EngineVersionID | 1 | |
| 1 | SIMPLE | IgnitionSystemType | eq_ref | PRIMARY | PRIMARY | 4 | icarcare_importfeeds.EngineConfig.IgnitionSystemTypeID | 1 | |
| 1 | SIMPLE | Mfr | eq_ref | PRIMARY | PRIMARY | 4 | icarcare_importfeeds.EngineConfig.EngineMfrID | 1 | |
| 1 | SIMPLE | Aspiration | eq_ref | PRIMARY | PRIMARY | 4 | icarcare_importfeeds.EngineConfig.AspirationID | 1 | |
| 1 | SIMPLE | FuelDeliveryConfig | eq_ref | PRIMARY | PRIMARY | 4 | icarcare_importfeeds.EngineConfig.FuelDeliveryConfigID | 1 | |
| 1 | SIMPLE | FuelSystemDesign | eq_ref | PRIMARY | PRIMARY | 4 | icarcare_importfeeds.FuelDeliveryConfig.FuelSystemDesignID | 1 | |
| 1 | SIMPLE | FuelDeliverySubType | eq_ref | PRIMARY | PRIMARY | 4 | icarcare_importfeeds.FuelDeliveryConfig.FuelDeliverySubTypeID | 1 | |
| 1 | SIMPLE | EngineDesignation | eq_ref | PRIMARY | PRIMARY | 4 | icarcare_importfeeds.EngineConfig.EngineDesignationID | 1 | |
| 1 | SIMPLE | EngineBase | eq_ref | PRIMARY | PRIMARY | 4 | icarcare_importfeeds.EngineConfig.EngineBaseID | 1 | |
| 1 | SIMPLE | CylinderHeadType | eq_ref | PRIMARY | PRIMARY | 4 | icarcare_importfeeds.EngineConfig.CylinderHeadTypeID | 1 | |
| 1 | SIMPLE | Parts | eq_ref | PRIMARY | PRIMARY | 4 | icarcare_importfeeds.Import_Values.part_type_id | 1 | Using where |
| 1 | SIMPLE | FuelSystemControlType | eq_ref | PRIMARY | PRIMARY | 4 | icarcare_importfeeds.FuelDeliveryConfig.FuelSystemControlTypeID | 1 | |
| 1 | SIMPLE | BaseVehicle | eq_ref | PRIMARY | PRIMARY | 4 | icarcare_importfeeds.Import_Values.base_vehicle_id | 1 | Using where |
| 1 | SIMPLE | Make | eq_ref | PRIMARY | PRIMARY | 4 | icarcare_importfeeds.BaseVehicle.MakeID | 1 | |
| 1 | SIMPLE | Model | eq_ref | PRIMARY | PRIMARY | 4 | icarcare_importfeeds.BaseVehicle.ModelID | 1 | |
| 1 | SIMPLE | Vehicle | eq_ref | PRIMARY,BaseVehicleID | PRIMARY | 4 | icarcare_importfeeds.VehicleConfig.VehicleID | 1 | Using where |
| 1 | SIMPLE | SubModel | eq_ref | PRIMARY | PRIMARY | 4 | icarcare_importfeeds.Vehicle.SubModelID | 1 | |
| 1 | SIMPLE | FuelDeliveryType | eq_ref | PRIMARY | PRIMARY | 4 | icarcare_importfeeds.FuelDeliveryConfig.FuelDeliveryTypeID | 1 | |
+----+-------------+-----------------------+--------+-----------------------+---------+---------+-----------------------------------------------------------------+--------+-------------------+
27 rows in set (2 hours 39 min 30.51 sec)
有什么我能做的嗎? 我試過分析表格,優化它們等等。似乎必須要做的事情要比讓它運行2小時更多,哈哈。
您確定您的查詢在邏輯上是正確的嗎? 我對你的數據庫一無所知,所以我不知道發生了什么,但這里有一小部分查詢似乎違反了查詢中其余查找設置的模式。
這里是:
INNER JOIN Vehicle
ON Import_Values.base_vehicle_id=Vehicle.BaseVehicleID
鑒於您的其余查詢,這看起來很奇怪。 我本來期望ON條件是基於Vehicle.VehicleID在Vehicle中查找一個條目,這可能是該表中的索引字段。 相反,它正在根據Vehicle.BaseVehicleID查找它,這可能是一個未編入索引的字段。
完全有可能這在邏輯上是正確的。 但如果它在邏輯上不正確,它可以解釋長時間的延遲。 如果情況確實如此,那么除了花費太長時間完成之外,您的查詢將提供錯誤的結果。
編輯:
ImportValues,Vehicle和VehicleConfig之間有什么關系? 一輛車有很多VehicleConfigs嗎? 或反之亦然?
看起來解釋計划最終使用的計划相當於ImportValues和VehicleConfig之間的笛卡爾連接。 笛卡爾聯合產生預期結果是非常不尋常的。 無論如何,你可以期待笛卡爾式加入需要很長時間。 即使查詢沒有產生笛卡爾連接,如果計划使用相同的算法,它仍然需要很長很長時間。
第二編輯:
還有另一個看似異常的連接條件。 這是VehicleConfig下的連接條件。
INNER JOIN VehicleConfig
ON Vehicle.VehicleID=VehicleConfig.VehicleID
這是一個非常好的連接條件,但不適用於VehicleConfig表。 用簡單的英語說,它說的是VehicleConfig確定車輛。 考慮到表格和列的名稱,這並不奇怪。
但是什么決定了VehicleConfig?
如果答案是“什么都沒有”,那么除了在Import_Values上進行全面掃描之外,糟糕的舊MySQL正在對表進行全面掃描也就不足為奇了。
我的結論是:修復你的查詢,以便27個表中的26個由引用表的PK的FK確定。 您的24個聯接已經符合此標准。 當您最終完成並執行解釋計划時,您應該只看到一個表執行全表掃描,即Import_Values表。
它應該運行得更快,並且更有可能產生正確的結果。
在查看您的解釋計划時,除了Import_Values和VehicleConfig之外,它看起來很好。 它甚至看起來都沒有考慮到VehicleConfig的任何鍵,只是直接進入全表掃描,這是不好的。
嘗試在VehicleID和BedConfigID上為VehicleConfig創建復合索引,在base_vehicle_id和part_type_id上為Import_Values創建索引。 如果它們已經有索引,則可能只需要更新可以使用以下命令執行的統計信息。 希望有所幫助。
ANALYZE TABLE VehicleConfig
ANALYZE TABLE Import_Values
請在執行此查詢時嘗試應用執行計划,並查看是否未建議任何缺少的鍵/索引。
嘗試設置forceplan並運行查詢。 另一個建議是將查詢分解為多個查詢,每個查詢中有6-7個表連接。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.