2016-09-29 4 views
0

Ich habe eine Abfrage mit einer langen Liste (> 2000 ids) in einem WHERE IN-Klausel in MySQL (InnoDB):Mysql: Warum ist in diesem Fall viel schneller als JOIN?

SELECT id 
FROM table 
WHERE user_id IN ('list of >2000 ids') 

ich dies wie dies durch die Verwendung eines INNER JOIN anstelle des bei zu optimieren versucht (beide IDs und die user_id verwenden, um einen Index):

SELECT table.id 
FROM table 
INNER JOIN users ON table.user_id = users.id WHERE users.type = 1 

jedoch überraschenderweise die erste Abfrage ist viel schneller (um den Faktor 5 bis 6). Warum ist das der Fall? Könnte es sein, dass die zweite Abfrage die erste übertrifft, wenn die Anzahl der IDs in der WHERE-Klausel viel größer wird?

+0

Führen Sie 'explain select ...' aus, um den Plan der Abfragen zu erhalten. –

+0

Erstens, vielleicht users.type hat keinen Index? Zweitens, Join ist eine teure Sache, weil es alle Zeilen scannen und Tabellen verbinden muss und dann Lookup durchführen. In der ersten Abfrage Sie sofort Lookup – Andrew

+1

Beachten Sie auch, dass, wie viel Sie passen in die IN-Klausel hängt von max_allowed_packet – e4c5

Antwort

1

Dies ist nicht Ans auf Ihre Frage, aber Sie können als Alternative für Ihre erste Abfrage verwenden, können Sie eine bessere Leistung erhöhen, indem IN Klausel mit EXISTS seit EXISTS Performance besser als IN ref ersetzt: Here

SELECT id 
FROM table t 
WHERE EXISTS (SELECT 1 FROM USERS WHERE t.user_id = users.id) 
+0

Diese Diskussion ist über MySQL und nicht SQL-Server (Beschwerde über Ihre Referenz) – e4c5

+0

Nun, aber Mechanismus dahinter ist gleich –

0

Dies ist ein unfairer Vergleich zwischen den 2 Abfragen.

  • In der ersten Abfrage eine Liste von Konstanten als Suchkriterien zur Verfügung stellen, deshalb hat MySQL zu öffnen und nur Tisch und/oder 1-Indexdatei zu suchen.

  • In der zweiten Abfrage weisen Sie MySQL an, die Liste dynamisch aus einer anderen Tabelle zu beziehen und diese Liste wieder in die Haupttabelle aufzunehmen. Es ist auch nicht klar, ob Indizes zum Erstellen eines Joins verwendet wurden oder ob ein vollständiger Tabellenscan benötigt wurde.

Um einen fairen Vergleich zu haben, Zeit die Abfrage, die die Liste in der ersten Abfrage zusammen mit der selbst Abfrage verwendet zu erhalten. Oder versuchen

SELECT table.id FROM table WHERE user_id IN (SELECT users.id FROM users WHERE users.type = 1) 

Die oben die Liste der IDs holt dynamisch in einer Unterabfrage.

Verwandte Themen