2012-04-03 3 views
0

Warum dauert diese MySQL-Abfrage für eine Tabelle mit 17.000 Zeilen ewig (und endet nie)?Warum dauert diese einfache Abfrage für immer?

SELECT * FROM files_folders WHERE file IN (SELECT file FROM files_folders WHERE folder = 123); 

Grundsätzlich kann sich eine Datei in mehreren Ordnern befinden (eine physische Datei und ihre Kopien). Ich versuche, alle Dateien in Ordner 123 zu bekommen. In meinem Beispiel gibt es jetzt 2 Dateien in Ordner 123. ID # 4222 & ID # 7121. Aber diese 2 Dateien könnten auch in anderen Ordnern und im Ordner 123 sein.

Mache ich das falsch oder gibt es etwas, das mir fehlt?

Bearbeiten: Hier ist ein Beispiel für die Tabellenstruktur.

+--------------+ 
| file | folder| 
+------+-------+ 
| 1 | 1  | 
| 2 | 1  | 
| 1 | 2  | 
| 3 | 2  | 
| 4 | 3  | 
+------+-------+ 

Deshalb möchte ich alle Dateien auszuwählen (und die Kopien), die mit 1 in Ordnern sind, die zurückkommen würde:

+--------------+ 
| file | folder| 
+------+-------+ 
| 1 | 1  | 
| 2 | 1  | 
| 1 | 2  | 
+------+-------+ 

Da 1 Datei 1 sowohl in Ordnern und 2.

Vielen Dank.

+1

Haben Sie einen Index für 'Folder'? –

+0

Fehle ich etwas? Warum nicht einfach: 'SELECT * FROM files_folders WHERE Ordner = 123;' –

+0

Warum nicht einfach 'SELECT * FROM files_folders WHERE Ordner = 123'? Momentan wählen Sie die 'ID' aus, wobei' Folder = 123' und dann im Wesentlichen '*' mit 'ID = ID' ausgewählt wird. – David

Antwort

1

ein Selbst JOIN:

SELECT 
    ff.* 
FROM 
    files_folders AS ff 
    INNER jOIN files_folders AS f ON f.ID=ff.ID 
WHERE 
    f.Folder=123 
; 
+0

Das hat den Trick gemacht. Vielen Dank. – ademers

+0

Die eigentliche Abfrage, die ich versuchte, war ein 'DELETE'. Die SELECT-Funktion funktioniert gut, aber sobald ich sie in eine DELETE-Anweisung einfüge, dauert es ewig. Ich habe das 'SELECT ff. *' Von deiner Abfrage zu 'DELETE ff' ersetzt. Irgendwelche Gedanken darüber, warum es lange dauert? Vielen Dank. – ademers

+0

Mit einer DELETE-Operation wird der Self-Join für jede gelöschte Zeile ungültig gemacht, was den Performance-Gewinn negiert. Für DELETE ist es am besten, die Ordner-IDs in einer Abfrage auszuwählen und dann eine DELETE-Abfrage für die resultierende ID-Liste auszuführen. Auf diese Weise ist das Argument zu IN (...) konstant, was zu einem schnellen Löschen führt. –

2

Für jede Datei muss MySQL prüfen, ob sich ID in den Ergebnissen der Unterabfrage befindet. Es dauert O(N).

Es muss für N Dateien getan werden.

So ist die Komplexität Ihrer Abfrage O(N^2). 17k^2 = ~ 4*10^8 so sollte es etwa eine Minute dauern, vielleicht weniger.

Warum ist Ihre Abfrage nicht

SELECT ID FROM files_folders WHERE Folder = 123 

?

+0

Weil eine Datei auch in einem anderen Ordner sein kann. Ich werde meinen Beitrag mit einem Beispiel für die Tabellenstruktur aktualisieren. – ademers

-1

Warum sind Sie Sub-Abfrage verwenden? Ich glaube nicht, dass es überhaupt nötig ist. Sie können nur direkt aus der Tabelle wählen wie

SELECT * FROM files_folders WHERE Folder = 123 

und eine zweite Sache:

„Weil eine Datei auch in einem anderen Ordner sein können“

Was bedeutet es bedeutet sub zu verwenden Abfrage?

+0

Fix deine Grammatik das nächste Mal, wenn Sie eine Frage bitte beantworten. Es ist schwer zu verstehen, was du zu sagen versuchst, wenn du schlechte Grammatik hast. – ragingasiancoder

Verwandte Themen