2016-05-10 8 views
1

Ich habe die folgende Abfrage,Sub-Abfrage auf großen Tisch mit verbinden extrem langsam

SELECT * FROM users, 
(SELECT * 
FROM mastery 
WHERE champion_rank = 1 
ORDER BY global_rank ASC 
LIMIT 3) as ranks 
WHERE users.id = ranks.user_id 

Mastery 22M Reihen hat und Benutzer hat Reihen 5M. Die obige Abfrage dauert 1800 ms.

Das Problem ist, dass die Unterabfrage nach, wenn sie von selbst laufen 2,5 ms dauert

SELECT * 
FROM mastery 
WHERE champion_rank = 1 
ORDER BY global_rank ASC 
LIMIT 3 

auszuführen, und einen einzelnen Benutzer von Benutzer-Tabelle nimmt 2,5 ms

SELECT * FROM users WHERE id = 4234523 

So theoretisch abrufen, wenn Ich habe nur meinen Code geändert, um die erste Unterabfrage durchzuführen, und dann für jede Zeile, die zurückgegeben wird, eine zusätzliche Abfrage auszuführen, würde der gesamte Prozess 2.5 + (3 * 2.5) = 10 ms dauern.

Sicher Postgres seltsam, etwas zu tun?

Struktur und Indizes von Datenbanken können here

+2

warum nicht beitreten benutzen? Haben Sie auch Indizes auf den Tisch gelegt? – JanR

+0

Bitte lesen Sie http://stackoverflow.com/tags/postgresql-performance/info und http://wiki.postgresql.org/wiki/SlowQueryQuestions dann [Bearbeiten] Ihre Frage ein und fügen Sie die fehlenden Informationen –

Antwort

0

Ihre Abfrage wird langsam zu finden, weil es die sortierten Unterabfrage für jede auf den 5M Reihen in Benutzer ausgeführt hat.

Sie wäre viel besser dran mit einem einzigen Durchgang teilnehmen zu tun, und verwendet Rang() Fensterfunktion der 3 oben, die Sie wollen filtern:

SELECT users.*, (ranks.mastery).* 
FROM (
    SELECT mastery, rank() OVER (ORDER BY global_rank) 
    FROM mastery 
    WHERE champion_rank = 1 
) as ranks 
JOIN users ON (users.id = ranks.user_id) 
WHERE ranks.rank <= 3; 
+0

Dank das funktioniert super, ich löste dies, indem der Datentyp von mastery.user_id und users.id geändert wurde, aber das ist etwas performanter. Nicht 100% es versteht, sondern wird versuchen, wenn ich nach Hause komme von der Arbeit – jromaior

0

die Frage bestimmt, wobei der Datentyp für die beiden Felder ich war mit dabei, waren anders. Die Benutzer-ID von Mastery hatte den Datentyp numerisch und die Benutzer-ID hatte den Datentyp integer. Sie musste jede Zeile auf den neuen Typ umwandeln.

Daraus ergibt sich die lange Abfragezeit.

+0

die etwas, das in dem Ausführungsplan gesehen werden konnte, wenn Sie das zu Ihrer Frage hinzugefügt hatten. –

+0

Im definetly keine Postgres-Experten, habe ich auf dem einen Blick ERKLäRT die Abfrage analysiert, sondern von der nicht intuitiv der Lage war, um herauszufinden, dass dies das Problem war, aber ich denke, das weitgehend mit Postgres aufgrund meiner Unerfahrenheit ist – jromaior

+0

Was Ich meinte, du hättest deiner ersten Frage den Ausführungsplan hinzufügen sollen. Wahrscheinlich hätte das jemand sofort bemerkt. –