2016-07-20 15 views
-1

Ich baue eine Abflachung Abfrage für einige Daten und ich habe zu diesem Fremdschlüssel, der die Abfrage führt plötzlich von 0.031s läuft in 2.460 ausgeführt wird s. Ich analysierte die Abfrage und die Verknüpfung wird als ALL Join mit der zusätzlichen Using where; Using join buffer (Block Nested Loop) statt einer eq_ref Join durchgeführt.MySql Join Typ Weirdness (mit "ALL" anstelle von "eq_ref")

In dem Bemühen, herauszufinden, was vor sich geht, habe ich eine Kopie der beiden Tabellen erstellt und sie auf das Nötigste reduziert. Die Tabellendefinitionen sind:

CREATE TABLE `zz_submission` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `rcId` int(11) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `idx_rcId` (`rcId`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

CREATE TABLE `zz_rc` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(255) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

zz_rc hat 5 Zeilen mit Namen. zz_submission hat 5 Zeilen mit gültigen IDs von RC.

Wenn ich diese Abfrage der "Typ" für die Tabelle laufen r ist all:

explain SELECT 
    s.ID, 
    r.name 
FROM zz_submission s 
    LEFT JOIN zz_rc r ON s.rcId = r.id 
; 

Image 1

Wenn ich diese Abfrage ausführen "Typ" für die Tabelle r ist eq_ref:

explain SELECT 
    s.ID, 
    r.id 
FROM zz_submission s 
    LEFT JOIN zz_rc r ON s.rcId = r.id 
; 

Image 2

Warum wirkt sich die Auswahl der Spalte ID vs. Name in der Join-Tabelle auf den Join-Typ aus? Ich habe dies auf meiner ursprünglichen Abfrage getestet und es wird wieder in 0.031s ausgeführt.

Was kann ich tun, damit die Query den eq_ref-Join hier verwendet?

+0

Sie zeigen nicht die EXPLAIN-Ausgabe, die Gesamtzahl der Zeilen. Ihre Frage fehlt Detail – Drew

+0

Sie strippten sie zu sehr. Für ** 5 ** -Zeilen ist es schneller, die Tabelle zu durchsuchen, als einen beliebigen Index zu verwenden. –

+0

Entschuldigung, ich habe die EXPLAIN-Ausgabe hinzugefügt. – William

Antwort

0

Ihre Abfrage scheint die gesamte s Tabelle zu lesen, dann lesen Sie viel oder alle der r Tabelle, richtig?

Using join buffer bedeutet, dass es die erforderlichen Daten von r in den Puffer lädt. Dies kann in einem schnellen Durchlauf über den Index erfolgen (in Ihrem Fall der PK). Dann können Suchvorgänge im RAM ausgeführt werden, ohne r weiter zu schlagen.

Die erste SELECT benötigt sowohl id als auch name; die zweite benötigt nur id. Basierend auf den Datentypen (und keinem Wissen von mir, oder dem Optimierer, der Sperrigkeit dieser VARCHAR) würde man annehmen, dass [ID, Name] viel größer als nur [ID] wäre.

Der "Join Buffer" ist von begrenzter Größe - SHOW VARIABLES LIKE 'join_buffer_size';. Es könnte also alles von [id] halten, aber nicht groß genug sein für [id, name].

Haben Sie wirklich names irgendwo in der Nähe von 255 Zeichen lang? Ihr Beispiel könnte ein guter sein, warum 255 nicht für alle Standardeinstellungen sein sollte.

eq_ref bedeutet, dass es in r eine einigermaßen effiziente Suche durchführen wird. Aber das ist wahrscheinlich langsamer als Using join buffer.

Block Nested Loop bedeutet, grob: Schleife durch s, für jede Zeile in r erreichen.

Jede Verbindung kann einen "Join Buffer" zuweisen, also nicht größer als 1% des RAMs machen.

+0

Korrekt. S ist mein Haupttisch und ich bekomme alle Zeilen davon. Ich schließe mich dem FK von R an, um einen Statusnamen zu erhalten. Ich verstehe nicht, warum der Join-Typ und die Ausführungszeit so drastisch variieren, nur basierend auf der Spalte, die ich aus der verbundenen Tabelle auswähle. – William