2017-03-15 3 views
0

Die folgende MySQL-Abfrage, die doppelt verschachtelten Unterabfragen verwendet, ist zu langsamNested Subquery zu langsam

SELECT t.name 
FROM creatives AS c 
INNER JOIN term_relationships AS tr ON tr.creative_id=c.creative_id 
INNER JOIN terms AS t ON t.term_id=tr.term_id 
WHERE c.creative_id IN 
    (SELECT creative_id 
    FROM term_relationships 
    WHERE term_id IN 
     (SELECT offer_term_id 
     FROM offer_urls)) 
AND t.taxonomy LIKE 'ad_network'; 

Die innere Abfrage

SELECT creative_id 
    FROM term_relationships 
    WHERE term_id IN 
     (SELECT offer_term_id 
     FROM offer_urls) 

extrem schnell ist (0,04 Sekunden)

aber die volle Abfrage liefert die Ergebnisse nicht. Ich gab nach etwa fünf Minuten Wartezeit auf.

Irgendeine Möglichkeit, dies zu optimieren?

+0

warum nicht versuchen Sie stattdessen eine 'LINKE OUTER JOIN' und einen Null-Check? Während diese nächste Aussage reine Vermutung ist, würde ich annehmen, dass die Unterabfragen pro abgerufener Zeile ausgeführt werden (also Zeile a, führt eine Unterabfrage für alle Zeilen b aus, die einzeln für alle Zeilen ausgeführt werden). – Rogue

+0

Sind Ihre Tabellen ordnungsgemäß indiziert? –

Antwort

2

Versuche:

SELECT t.name 
FROM creatives AS c 
JOIN term_relationships AS tr ON tr.creative_id=c.creative_id 
JOIN terms AS t ON t.term_id=tr.term_id 
JOIN term_relationships tr2 ON tr2.creative_id = c.creative_id 
JOIN offer_urls ou ON ou.offer_term_id = tr2.term_id 
WHERE t.taxonomy LIKE 'ad_network'; 

Diese Version geschrieben nur mit JOIN viel schneller sein wird.

+0

Sie sollten vielleicht erklären, warum Sie weglassen können, wo .. in .. Teil :), aber Ihre Lösung ist die gleiche ich kam mit – r3bel

+0

Ich bearbeitete die Antwort eine Minute nach dem Posting, um die 'where' hinzuzufügen, vermisste ich es in der Kopierpaste – Gab

+0

Leider funktioniert diese Logik nicht für mich. Für jede offer_term_id habe ich viele Datensätze in term_relationships-Tabelle. Jeder Datensatz gibt mir eine creative_id. Jetzt muss ich mit jeder creative_id in der Tabelle term_relationships erneut eine sekundäre Suche durchführen. Aus diesem Datensatz muss ich die Datensätze filtern, die die Taxonomie erfordern. Ich hoffe, ich habe hier einen Sinn ergeben. Es ist sehr schwer für jemanden, all das zu verstehen, ohne auf die Tische zu schauen. Aber danke für deine Hilfe. Wenn Sie einen anderen Vorschlag haben, lassen Sie es mich bitte wissen. Denken über die Aufspaltung der Abfragen und lassen Sie PHP einige Logik behandeln – hvs

0

Versuchen Umschreiben dies mit exists:

SELECT t.name 
FROM terms t JOIN 
    term_relationships tr 
    ON t.term_id = tr.term_id JOIN 
    creatives c 
    ON tr.creative_id = c.creative_id 
WHERE EXISTS (SELECT 1 
       FROM term_relationships tr2 JOIN 
        offer_urls ou 
        ON tr.term_id = ou.offer_term_id 
       WHERE c.creative_id = tr2.creative_id 
      ) AND 
    t.taxonomy LIKE 'ad_network'; 

Dann hierfür die folgenden Indizes wollen:

  • Begriffe (Taxonomie, term_id)
  • offer_urls (offer_term_id)
  • term_relationships (creative_id, term_id);
  • Motive (creative_id)

Sie haben bereits einige dieser unter Verwendung von Primärschlüsseldefinitionen definiert.