2017-07-14 2 views
0

Below Abfragezeiten, nachdem diese zwei Zeilen oder jede einzelne davonPostgres 9.4 SQL-Abfrage Timeout

AND final IS NOT NULL 
ORDER BY tmodified ASC 

Abfrage hält mehr als 10 min laufen .... und Auszeit hinzufügen.

Wenn ich über zwei Zeilen entferne, gibt es die Ergebnisse innerhalb von 1 Millisekunden zurück, was Ok funktioniert.

Eine Idee, wie kann ich über zwei Zeilen arbeiten mit unten Abfrage?

Tabelle table_h hat 36 Millionen Platten und in dieser Tabelle

column final is numeric(10,5) 
column tmodified is bigint, Timestamp 

Ich bin mit Postgres 9.4

Dies ist die komplette Abfrage.

SELECT DISTINCT t.cid, h.a, am.b, u2.c, u.d, h.e, ie.f, im.g FROM table_am as am 
    INNER JOIN table_t as t on (t.id = am.id AND t.type = am.type) 
    INNER JOIN table_h AS h on h.iid = t.id 
    INNER JOIN table_u AS u ON u.id = h.uid 
    INNER JOIN table_u AS u2 ON u2.id = h.lu 
    INNER JOIN table_im AS im ON im.asid = am.sid 
    INNER JOIN table_ie AS ie ON ie.uid = u.uid 
    INNER JOIN table_g AS g ON g.id = h.oldid 
WHERE h.final >= 0 
    AND h.final IS NOT NULL 
    AND h.tmodified >= 1499903419 
    AND ie.p = im.p 
    AND h.sr IN ('x', 'y', 'z') 
    AND h.id = (SELECT id FROM table_h WHERE oldid = h.oldid AND final >= 0 
       AND final IS NOT NULL -- Issue is here and 
       ORDER BY tmodified ASC -- Issue is here 
       LIMIT 1) 
    AND h.id NOT IN (SELECT id FROM table_m WHERE tmodified > 1499903419) 
+0

Was ist 36 Millionen mal 36 Millionen? Eine sehr große Anzahl. Sie sollten diese korrelierte Unterabfrage loswerden. –

+0

keine Idee, wie man es verbessert? – Developer

+0

Wir müssten Ihre Anfrage neu schreiben. Meine Vermutung ist, dass die Abfrage nur mit der korrelierten Unterabfrage beendet werden kann. –

Antwort

1

Versuchen Sie, die korrelierte Unterabfrage mit einem Join zu ersetzen, etwa so:

SELECT ... 
FROM table_am as am 
... 
INNER JOIN table_g AS g ON g.id = h.oldid 
INNER JOIN 
(
    SELECT id, oldid, MIN(tmodified) AS min_mod 
    FROM table_h 
    WHERE final >= 0 AND final IS NOT NULL 
    GROUP BY id, oldid 
) t 
    ON h.id  = t.id AND 
     h.oldid = t.oldid AND 
     h.tmodified = t.min_mo 

Beachten Sie, dass wir auch diese mit Zeilennummer oder eine andere analytische Funktion zum Ausdruck gebracht haben könnte, aber hoffentlich das gibt Ihnen einen Platz anfangen.

+0

tmodfied ist Zeitstempel, denken Sie, max wird letzten geänderten Datensatz zurückgeben? – Developer

+0

@Developer Danke, dass du das eingefangen hast. –

1

Nun, ich kann die Hälfte Ihres Problems lösen. Die Bedingung:

AND h.final IS NOT NULL 

wird nicht benötigt. Die Bedingung:

h.final >= 0 

berücksichtigt dies bereits.

Wenn die verbleibende Abfrage so schnell zurückkehrt, dann verwenden Sie eine Unterabfrage oder CTE und dann sortieren nach:

with cte as (
     select . . ., t.modified 
    ) 
select cte.* 
from cte 
order by modified; 
Verwandte Themen