e ショップ アプリケーションの一部を最適化するための支援をお願いしたいと思います。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,
}
アプリケーションは、車両の仕様を取得し、 vehicle_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 時間未満としましょう。このクエリは、新しい更新が入ったときに週に 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 時間クエリを実行しましたが、まだ完了していません。どんな提案でも喜んでします。