0

私は2つのテーブルを持っています:

CREATE TABLE IF NOT EXISTS `products` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `categoryId` int(10) unsigned DEFAULT NULL,
  `parentId` int(10) unsigned DEFAULT NULL,
  `barcode` varchar(255) DEFAULT NULL,
  `code` varchar(255) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_products_product_categories1_idx` (`categoryId`),
  KEY `fk_products_products1_idx` (`parentId`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=71521 ;

CREATE TABLE IF NOT EXISTS `inventory` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `depotId` int(10) unsigned NOT NULL,
  `productId` int(10) unsigned NOT NULL,
  `remain` int(11) DEFAULT NULL,
  `remain2` int(10) unsigned DEFAULT NULL,
  `updatedDateTime` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_inventory_depots1_idx` (`depotId`),
  KEY `fk_inventory_products1_idx` (`productId`),
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=89291 ;

次のクエリを最適化するのを手伝ってください (パフォーマンスを向上させるためにどのインデックスを追加する必要があるか)。クエリは 0.2578 秒かかりました (MySQL はインデックス fk_inventory_depots1_idx を使用しています)。AND i.depotId = 3 を削除すると、クエリは 0.5484 秒かかりました。EXPLAIN クエリは、Extra: Using where; を示しています。一時的な使用; ファイルソートの使用

SELECT `p`.* , SUM(i.remain) AS `remain` , SUM(i.remain2) AS `remain2`
FROM `products` AS `p`
LEFT JOIN `inventory` AS `i` ON p.id = i.productId
WHERE remain != 0 AND i.depotId = 3
GROUP BY `p`.`id`
ORDER BY `p`.`id` DESC
LIMIT 50 
4

2 に答える 2

0

sum()ステートメントで使用される関数は、すべての行を考慮します (句LIMITは最後に計算されるため有効ではありません)。のすべての値が合計されるためremain、完全なテーブル スキャンが発生する可能性があります。remain2

sum()最新の50 rows使用状況を知りたい場合

SELECT 
  `p`.* , 
  SUM(i.remain) AS `remain`, 
  SUM(i.remain2) AS `remain2`
FROM
  (
    SELECT `p`.*, 
          i.remain, 
          i.remain2 
    FROM 
      `products` AS `p`
      JOIN `inventory` AS `i` ON p.id = i.productId << This should be a JOIN, as remain and depotId belong to inventory
    WHERE 
      remain != 0 
      AND i.depotId = 3
    GROUP BY 
      `p`.`id`
    ORDER BY 
      `p`.`id` DESC
LIMIT 50  ) as t
于 2013-04-23T17:35:26.477 に答える
0

あなたのクエリは問題ないように見えますが、LEFT-JOIN として持っていますが、WHERE を使用すると !=0 と i.DepotID = 3 が強制的に INNER-JOIN になります。残りの数量がゼロ以外のエントリのみを意図していた場合は、問題ありません。ただし、在庫製品が必要な場合は、クエリを次のように調整する必要があります。

SELECT 
      `p`.* , 
      SUM(i.remain) AS `remain` , 
      SUM(i.remain2) AS `remain2`
   FROM `
      products` AS `p`
         LEFT JOIN `inventory` AS `i` 
            ON p.id = i.productId
           AND remain != 0 
           AND i.depotId = 3
   GROUP BY 
      `p`.`id`
   ORDER BY 
      `p`.`id` DESC
   LIMIT 50 

「ON」結合条件の微妙な違いに注目してください。これにより、一致する在庫レコードに関係なく、すべての商品が許可されます。そうは言っても、「DepotID = 3」基準のものだけでなく、すべての在庫から取得しています。

インデックス作成を支援するために、私が提案する唯一のことは、複数フィールド キーです。この場合、テーブル内のほとんどのフィールドを JOIN または SUM() の目的で使用しています。フィールドがインデックスの一部である場合、レコードごとの実際のデータ ページに戻る必要はありません。わずかな無駄ですが、最終結果が改善される可能性があります。

KEY fk_inventory_multiplefields_idx(productid、depotid、remain、remain2)、

于 2013-05-06T11:14:30.343 に答える