簡體   English   中英

如何使用JOIN加速復雜的SQL查詢

[英]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.

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