2009-08-07 9 views
3

für diese ein von MySQL - Find rows matching all rows from joined tableMySQL - Zeilen Alle Zeilen aus verknüpften Tabelle und String aus anderen Tabellen

Dank dieser Website verfolgen ist die Abfrage perfekt läuft.

Aber jetzt musste ich die Abfrage für eine Suche nach Künstler und Spur erweitern. Das hat mich auf die folgende Abfrage führen:

SELECT DISTINCT`t`.`id` 
FROM `trackwords` AS `tw` 
INNER JOIN `wordlist` AS `wl` ON wl.id=tw.wordid 
INNER JOIN `track` AS `t` ON tw.trackid=t.id 
WHERE (wl.trackusecount>0) AND 
(wl.word IN ('please','dont','leave','me')) AND 
t.artist IN ( 
SELECT a.id 
FROM artist as a 
INNER JOIN `artistalias` AS `aa` ON aa.ref=a.id 
WHERE a.name LIKE 'pink%' OR aa.name LIKE 'pink%' 
) 
GROUP BY tw.trackid 
HAVING (COUNT(*) = 4); 

Die Erklärung für diese Abfrage ziemlich gut aussieht, ich denke:

+----+--------------------+-------+--------+----------------------------+---------+---------+-----------------+------+----------------------------------------------+ 
| id | select_type  | table | type | possible_keys    | key  | key_len | ref    | rows | Extra          | 
+----+--------------------+-------+--------+----------------------------+---------+---------+-----------------+------+----------------------------------------------+ 
| 1 | PRIMARY   | wl | range | PRIMARY,word,trackusecount | word | 767  | NULL   | 4 | Using where; Using temporary; Using filesort | 
| 1 | PRIMARY   | tw | ref | wordid,trackid    | wordid | 4  | mbdb.wl.id  | 31 |            | 
| 1 | PRIMARY   | t  | eq_ref | PRIMARY     | PRIMARY | 4  | mbdb.tw.trackid | 1 | Using where         | 
| 2 | DEPENDENT SUBQUERY | aa | ref | ref,name     | ref  | 4  | func   | 2 |            | 
| 2 | DEPENDENT SUBQUERY | a  | eq_ref | PRIMARY,name,namefull  | PRIMARY | 4  | func   | 1 | Using where         | 
+----+--------------------+-------+--------+----------------------------+---------+---------+-----------------+------+----------------------------------------------+ 

Sehen Sie Raum für Optimierung? Query hat eine Laufzeit von ca. 7s, was leider sehr ist. Irgendwelche Vorschläge sind willkommen.

TIA

Antwort

1

Sie haben hier zwei mögliche selektive Bedingungen: artists's name und word list.

Unter der Annahme, dass die Worte selektiver sind als Künstler:

SELECT tw.trackid 
FROM (
     SELECT tw.trackid 
     FROM wordlist AS wl 
     JOIN trackwords AS tw 
     ON  tw.wordid = wl.id 
     WHERE wl.trackusecount > 0 
       AND wl.word IN ('please','dont','leave','me') 
     GROUP BY 
       tw.trackid 
     HAVING COUNT(*) = 4 
     ) tw 
INNER JOIN 
     track AS t 
ON  t.id = tw.trackid 
     AND EXISTS 
     (
     SELECT NULL 
     FROM artist a 
     WHERE a.name LIKE 'pink%' 
       AND a.id = t.artist 
     UNION ALL 
     SELECT NULL 
     FROM artist a 
     JOIN artistalias aa 
     ON  aa.ref = a.id 
       AND aa.name LIKE 'pink%' 
     WHERE a.id = t.artist 
     )     

Sie müssen die folgenden Indizes haben für diese effizient sein:

wordlist (word, trackusecount) 
trackwords (wordid, trackid) 
artistalias (ref, name) 
+0

wow, nice. Ich glaube, ich verstehe, was Sie tun, aber mysql gibt: # 1248 - Jede abgeleitete Tabelle muss einen eigenen Alias ​​haben soweit ich es verstehe, sollte es die Spur sein (t), die den Fehler gab, aber ich kann nicht herausfinden, wie ich das beheben kann. – Rufinus

+0

@Rufinus: Oh, Entschuldigung. Fest. – Quassnoi

+1

'@ Rufinus': Es wäre sehr schön, wenn Sie die Tabellendefinitionen zusammen mit der Abfrage veröffentlichen würden, damit die Benutzer die Syntax vor dem Posten überprüfen können. – Quassnoi

0

Haben Sie indiziert bereits die Namen Spalten? Das sollte das beschleunigen.

Sie können auch die Volltextsuche mit Match und Again versuchen.

Verwandte Themen