0

我想请您帮忙优化电子商店应用程序的一部分。我有一个在 MySQL 上运行的数据库,在进行大型产品导入时,我在性能上苦苦挣扎。特别是,有以下表格(省略不重要的字段):

这是商店中可用的产品表。除此信息外,它还包含价格、成本、尺寸和其他目前不重要的内容,大小约为 15,000 行。

product {
  `product_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `model_number` varchar(16) NOT NULL,
  `codemaster_id` int(16) NOT NULL
} 

该表设置了所有车辆的配置,这些车辆的大小约为 500,000 行。

vehicle_superconfig {
  `EngineConfigID` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `EngineDesignationID` int(11) NOT NULL,
  `EngineVINID` int(11) NOT NULL,
  `ValvesID` int(11) NOT NULL,
  `EngineBaseID` int(11) NOT NULL,
  `FuelDeliveryConfigID` int(11) NOT NULL,
  `AspirationID` int(11) NOT NULL,
  `CylinderHeadTypeID` int(11) NOT NULL,
  `FuelTypeID` int(11) NOT NULL,
  `IgnitionSystemTypeID` int(11) NOT NULL,
  `EngineMfrID` int(11) NOT NULL,
  `EngineVersionID` int(11) NOT NULL,
  `PowerOutputID` int(11) NOT NULL,
  `VehicleID` int(11) NOT NULL,
  `BaseVehicleID` int(10) unsigned NOT NULL,
  `SubmodelID` int(11) unsigned NOT NULL,
  `SteeringConfigID` int(32) NOT NULL,
  `DriveTypeID` int(10) NOT NULL,
}

此表规定了零件适用于车辆的要求(例如,该螺钉进入 BMW 328i 并仅在欧洲提供这种类型的发动机,它需要预先安装一些其他零件等。如果没有要求对于特定区域,该属性设置为 0(例如,后视镜不关心汽车发动机是否使用汽油或柴油或其他任何东西)。大约大小为 10,000 行。

product_application{
  `ID` int(32) unsigned NOT NULL AUTO_INCREMENT,
  `product_id` int(10) unsigned NOT NULL,
  `basevehicle_id` int(10) unsigned NOT NULL,
  `submodel_id` int(10) unsigned NOT NULL,
  `EngineConfigID` int(10) unsigned NOT NULL,
  `EngineDesignationID` int(11) NOT NULL,
  `EngineVINID` int(11) NOT NULL,
  `ValvesID` int(11) NOT NULL,
  `EngineBaseID` int(11) NOT NULL,
  `FuelDeliveryConfigID` int(11) NOT NULL,
  `AspirationID` int(11) NOT NULL,
  `CylinderHeadTypeID` int(11) NOT NULL,
  `FuelTypeID` int(11) NOT NULL,
  `IgnitionSystemTypeID` int(11) NOT NULL,
  `EngineMfrID` int(11) NOT NULL,
  `EngineVersionID` int(11) NOT NULL,
  `PowerOutputID` int(11) NOT NULL,
  `VehicleID` int(11) NOT NULL,
  `BaseVehicleID` int(10) unsigned NOT NULL,
  `SubmodelID` int(11) unsigned NOT NULL,
  `SteeringConfigID` int(32) NOT NULL,
  `DriveTypeID` int(10) NOT NULL,
  ... several other fields that are not used in the queries here
}

// this table determines what kind of part we have
// and where it belongs (e.g. that it is a mirror on right side)
// approximate size 30,000 rows
part_codemaster { 
  `codemaster_id` int(16) NOT NULL,
  `part_type` int(16) NOT NULL,
  `position` int(8) NOT NULL,
}

应用程序获取车辆规格,确定车辆 ID 和引擎配置,并应该列出适合该车辆的部件。位置包括在内,因为某些产品适合很多地方(例如螺丝) 我需要根据上表中的数据填写此表缺少连接(表产品中大约 500 种新产品)。

product_to_vehicle {
  `ID` int(64) NOT NULL,
  `product_id` int(10) NOT NULL,
  `vehicle_id` int(10) NOT NULL,
  `engine_config_id` int(16) NOT NULL,
  `position` int(8) NOT NULL
}

如前所述,我的任务是将缺失的连接填充到新导入产品的表 product_to_vehicle 中。我的问题是如何在合理的时间内做到这一点(让我们说在 1 小时内 - 当新的更新出现时,这个查询将在命令行上运行一次左右)。我特别感兴趣的是:

  • 我的查询有点愚蠢吗?怎么写比较好?
  • 我应该为表生成哪些索引?我的猜测是每一列的索引是不够的......
  • 我应该使用什么类型的表(InnoDB 或 MyISAM)?
  • 还有什么可以帮助的吗?

我现在使用的查询是:

START TRANSACTION;
INSERT IGNORE INTO 
    product_to_vehicle(product_id, vehicle_id, engine_config_id, position) (
    SELECT DISTINCT
        att.product_id,
        sup.vehicle_id,
        sup.engine_config_id,
        c.position as position
    FROM
        product_application as att,
        vehicle_super as sup,
        product as p,
        codemaster as c
    WHERE p.product_id > 10000 AND p.product_id < 10500
      AND (sup.base_vehicle_id = att.base_vehicle_id OR att.base_vehicle_id = 0)
      AND (sup.submodel_id = att.submodel_id OR att.submodel_id = 0)
      AND (att.AspirationID = sup.AspirationID OR att.AspirationID = 0)
      AND (att.DriveTypeID = sup.DriveTypeID OR att.DriveTypeID = 0)
      AND (att.CylinderHeadTypeID = sup.CylinderHeadTypeID OR att.CylinderHeadTypeID =  0)
      AND (att.FuelTypeID = sup.FuelTypeID OR att.FuelTypeID = 0)
      AND (p.CodeMasterID = c.CodeMasterID)
      AND (att.ProductID = p.product_id)
  );
COMMIT;

我为单个产品(p.product_id = 10000)运行了大约 4 个小时的查询,但它仍然没有完成。我很乐意提出任何建议。

4

0 回答 0