0

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 時間クエリを実行しましたが、まだ完了していません。どんな提案でも喜んでします。

4

0 に答える 0