繁体   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