web-dev-qa-db-ja.com

mysql:左結合がインデックスを使用しないのはなぜですか?

Mysqlクエリで奇妙なパフォーマンスの問題に直面しています。

SELECT
`pricemaster_products`.*,
`products`.*
FROM `pricemaster_products`
LEFT JOIN `products`
ON `pricemaster_products`.`ean` = `products`.`products_ean`

明示的に左結合を使用したいと思います。ただし、クエリには必要以上に時間がかかります。

結合をINNERJOINに変更しようとしました。クエリは非常に高速になりましたが、結果は私が必要とするものではありません。

私はexplainを使用して、次の結論に達しました。

「LEFTJOIN」を使用すると、クエリのEXPLAINは次のようになります...

type: "ALL"
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 90.000 / 50.000 (the full number of the corresponding table)

...両方のテーブル。

「INNERJOIN」を使用すると、EXPLAINは次のようになります。

テーブル「製品」の場合:

Same result as above.

テーブル「pricemaster_products」の場合:

type: "ref"
possible_keys: "ean"
key: ean
key_len: 767
ref: func
rows: 1
extra: using where

どちらのテーブルにも、関連する列にインデックスが設定されています。 LEFT JOINが非常に遅いと私が考えることができる唯一の理由は、インデックスをまったく使用しないことです。しかし、なぜそうではないのでしょうか?

テーブルの構造は次のとおりです。

CREATE TABLE IF NOT EXISTS `pricemaster_products` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `provider` varchar(255) CHARACTER SET utf8 NOT NULL,
  `ean` varchar(255) CHARACTER SET utf8 NOT NULL,
  `title` varchar(255) CHARACTER SET utf8 NOT NULL,
  `gnp` double DEFAULT NULL,
  `vat` int(11) DEFAULT NULL,
  `cheapest_price_with_shipping` double DEFAULT NULL,
  `last_cheapest_price_update` int(11) DEFAULT NULL,
  `active` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `ean` (`ean`),
  KEY `title` (`title`),
  KEY `gnp` (`gnp`),
  KEY `vat` (`vat`),
  KEY `provider` (`provider`),
  KEY `cheapest_price_with_shipping` (`cheapest_price_with_shipping`),
  KEY `last_cheapest_price_update` (`last_cheapest_price_update`),
  KEY `active` (`active`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=58436 ;

CREATE TABLE IF NOT EXISTS `products` (
  `products_id` int(11) NOT NULL AUTO_INCREMENT,
  `products_ean` varchar(128) DEFAULT NULL,
  `products_status` tinyint(1) NOT NULL DEFAULT '1',
  [a lot more of fields with no connection to the query in question]
  PRIMARY KEY (`products_id`),
  KEY `products_status` (`products_status`),
  KEY `products_ean` (`products_ean`),
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=105518 ;
21
Majiy

結合に関連する2つのフィールドは、まったく同じタイプではありませんでした(charACTER SET utf8のvarchar(255)とlatin1のvarchar(128))。両方を同じ長さと文字セットに設定しましたが、LEFTJOINを使用したクエリは期待どおりに機能します。

51
Majiy