mysql: pourquoi ne jointure gauche de ne pas utiliser un index?

Je suis confronté à un étrange problème de performance avec une requête mysql.

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

J'ai explicitement souhaitez utiliser une jointure gauche. Mais la requête prend beaucoup plus de temps qu'il ne le devrait.

J'ai essayé de changer le rejoindre pour une JOINTURE INTERNE. La requête est maintenant vraiment rapide, mais le résultat n'est pas ce dont j'ai besoin.

J'ai utilisé expliquer et est venu à la conclusion suivante:

Si j'utilise un "LEFT JOIN" puis une EXPLIQUER les résultats de la requête dans...

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

... pour les deux tables.

Si j'utilise un "INNER JOIN" alors EXPLIQUEZ donne:

Pour la table "produits":

Same result as above.

Pour la table "pricemaster_products":

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

Les deux tables ont des indices de jeu sur les colonnes concernées. La seule raison pour laquelle je pouvais penser pour le LEFT JOIN pour être si lent, c'est qu'elle ne fait pas l'utilisation de l'indice à tous. Mais pourquoi ne serait-il pas?

La structure de la table est comme suit:

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 ;
  • La version de MySQL que vous avez?
  • Version de MySQL est 5.1.70
  • non, c'est "donnez-moi toutes les données dans la table de gauche et toutes les données disponibles dans le tableau de droite". vous êtes en train de penser une jointure externe complète
  • Combien d'enregistrements vous travaillez ici? Les Jointures internes sont toujours plus vite que la Gauche Rejoint, en particulier lorsqu'ils traitent avec un grand nombre d'enregistrements.
  • pricemaster_products a 58.000 lignes, de produits a 90.000. J'ai édité les parties pertinentes de la structure de la table en question.
  • Eh bien, la ean est une table est un varchar(255) avec CHARACTER SET utf8 et dans l'autre un varchar(128) avec latin1. Cela peut s'avérer pertinent.
  • Qui était-il! Je n'ai mis les deux pour être de type varchar(255) du jeu de caractères. Fonctionne parfaitement maintenant.

InformationsquelleAutor Majiy | 2013-09-06