Hallo,
ich habe zwei Tabellen, eine mit Produkten 'products', eine mit Listen 'lists'. Diese stehen zueinander in einer m:n-Beziehung. Ein Produkt kann also in mehreren Listen enthalten sein und eine Liste kann mehrere Produkte zusammenfassen. Dafür habe ich eine Verknüpfungstabelle 'prods_lists'.
Mein Ziel:
Ich möchte sämtliche Produkte haben mit Ausnahme von solchen, die in ganz bestimmten Listen enthalten sind. Die IDs dieser speziellen Listen habe ich, sagen wir mal 1, 2 und 3.
Es läuft MySQL v5.0.30
Das ganze löse ich mit einem doppelten Subquery:
SELECT id_products
FROM products
WHERE id_products NOT IN
(SELECT id_products
FROM prods_lists AS pl1
WHERE EXISTS
(SELECT id_lists
FROM prods_lists AS pl2
WHERE pl2.id_products = pl1.id_products
AND pl2.id_lists IN (1,2,3)
LIMIT 1
)
)
Produkte gibt es insgesamt etwa 30000. Produkte, die durch die speziellen Listen ausgeschlossen werden einige Hundert. Trotzdem dauert die Anfrage gut 30 Sekunden.
Meine erste Frage: Gibt es in meiner Anfrage grobe Nachlässigkeiten bzgl. Optimierung? Gibt es eine bessere Query? Ein Join wäre vielleicht schneller, aber ich bekomme ihn nicht hin, weil ein Produkt ja in mehreren Listen sein kann.
Nun habe ich mir das mal EXPLAINen lassen und es stellt sich heraus, dass die beiden Subselect beide abhängig sind, aber das sind sie doch gar nicht (nur die zweite natürlich)?
Die Query habe ich dann erstmal vereinfacht:
SELECT id_products
FROM products
WHERE id_products NOT IN
(SELECT DISTINCT id_products
FROM prods_lists
)
Hier ist ja offensichtlich, dass die Subquery unabhängig ist, aber MySQL schreibt bei Explain "Dependent subquery" hin und die ganze Query braucht immer noch 15 Sekunden.
Wenn ich das Ergebnis dieser Subquery manuell in die "NOT-IN-Liste" eintrage, ist das Ergebnis sofort da.
Für "possible_keys" nennt MySQL beim äußeren select "NULL", bei "keys " aber "PRIMARY".
Ich würde mich freuen, wenn ihr mich über das für mich seltsame Verhalten aufklären könntet! Danke!
Chris