我想请您帮忙优化电子商店应用程序的一部分。我有一个在 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 个小时的查询,但它仍然没有完成。我很乐意提出任何建议。