2013-09-06 22 views
18

Ich bin mit einer mysql-Abfrage ein seltsames Leistungsproblem konfrontiert.mysql: Warum verwendet linker Join keinen Index?

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

Ich möchte explizit eine linke Join verwenden. Aber die Abfrage braucht viel mehr Zeit als es sollte.

Ich habe versucht, den Beitritt zu einem INNEREN JOIN zu ändern. Die Abfrage ist jetzt sehr schnell, aber das Ergebnis ist nicht das, was ich brauche.

verwendet, erkläre ich und kam zu folgendem Ergebnis:

Wenn ich eine einer EXPLAIN der Abfrageergebnisse in ...

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

"LEFT JOIN" dann ... für beiden Tabellen .

Wenn ich ein "INNER JOIN" verwenden dann EXPLAIN gibt:

Für Tabelle "Produkte":

Same result as above. 

Für Tisch "pricemaster_products":

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

Beide Tabellen haben Indizes Stellen Sie die relevanten Spalten ein. Der einzige mögliche Grund, warum ich denken könnte, dass der LEFT JOIN so langsam ist, ist, dass er den Index überhaupt nicht benutzt. Aber warum sollte es nicht?

Die Tabellenstruktur ist wie folgt:

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 ; 
+0

Welche Version von MySQL haben Sie? –

+0

MySQL-Version ist 5.1.70 – Majiy

+1

@juergend: Nein, es ist "gib mir alle Daten in der linken Tabelle und alle verfügbaren Daten in der richtigen Tabelle". Sie denken eine volle äußere Verbindung –

Antwort

39

Die beiden relevanten Felder für die Verknüpfung nicht genau die gleiche Art (VARCHAR (255) mit Zeichensatz Utf8 und VARCHAR (128) mit latin1) hatte. Ich habe beide auf die gleiche Länge und den gleichen Zeichensatz gesetzt, und nun funktioniert die Abfrage mit dem LINKEN JOIN wie erwartet.

+3

Heilige F *** ing sh * t. Ich habe dieses Ding völlig übersehen. Vielen Dank. +1 –

+2

Vielen Dank, das half mir, ein Problem mit einer meiner Abfragen zu finden, wo eine Tabelle, die falsch erstellt wurde (mit dem falschen Zeichensatz), Probleme verursachte. +1 –

+1

Vielen Dank, ich hatte das gleiche Problem und es fuhr mich absolut Bananen – caro

Verwandte Themen