2016-07-29 9 views
1

Ive sehr seltsames Problem, wenn ich Abfrage wie unten ausführen:seltsame Leistung von Postgres Abfrage

with ap as (
    SELECT id from adress limit 1000) 
) 

SELECT distinct house.id, house.date 
FROM house 
WHERE house.adressid in (select id from ap) 

LIMIT 9999 

I ge die resulkts innerhalb von 100 ms

Aber wenn ich die Grenze auf 10 ändern dann Im a bekommen Ergebnis nach 20 s

with ap as (
    SELECT id from adress limit 1000) 
) 

SELECT distinct house.id, house.date 
FROM house 
WHERE house.adressid in (select id from ap) 

LIMIT 10 

natürlich Index auf adressid

ist
CREATE INDEX house_idx 
    ON house 
    USING btree 
    (adressid COLLATE pg_catalog."default"); 

Im Haus gibt es wie 9 Millionen Zeilen.

Hat jemand eine Idee hoiw kann ich versuchen, die Leistung zu verbessern. Ive reduziert das Problem auf diesen sehr einfach, aber die Struktur ist viel komplexer, das ist in Wirklichkeit, warum ich Dich mit Tisch bietet didnt Pläne erstellen und Abfrage ...

+3

I unter Verwendung von EXPLAIN ANALYZE, um herauszufinden, beginnen würde, wie postgresql tatsächlich die zwei Abfragen zu verarbeiten. – Gary

+0

Sie haben die Abfrage möglicherweise stark vereinfacht. Postgres (es sei denn, es hat eine sehr ungewöhnliche Optimierung) sollte die gleiche Arbeit für beide Abfragen machen - es muss die gesamte Liste für das 'select distinct' generieren, bevor das äußere' limit' angewendet wird. Es könnte etwas anderes passieren. –

+0

Eigentlich ist das die einzige Sache, die ich verändere – Snorlax

Antwort

0

, die eigentlich nicht überraschend:

Im ersten Fall ap hat bis zu 1000 Zeilen und das Ergebnis sollte bis zu 9999 haben, so dass der Optimierer zuerst adress setzen. Mit Index auf house ist die Abfrageleistung relativ hoch.

Im zweiten Fall ap hat noch bis 1000 Zeilen, aber die Ergebnismenge sollte nur bis zu 10 hat, so dass der Optimierer setzte house erste ... und endet mit 10 Tabellen-Scans auf adress von bis zu 1000 Zeilen nach oben jeder. Es wird wahrscheinlich nicht einmal in der Lage sein, einen Index zu verwenden, da es nirgendwo eine Order By-Klausel gibt.

Diese limit 1000 auf Adresse sieht wirklich verdächtig und kann möglicherweise zu inkonsistenten Ergebnissen führen: ohne Order By gibt es keine Garantie, die von adress aufzeichnet würde bei jedem Durchlauf berücksichtigt werden.

würde ich INNER JOIN verwenden Sie das Problem zu beheben:

SELECT DISTINCT house.id, house.date 
FROM house 
INNER JOIN adress ON adress.id = house.adressid 
ORDER BY house.date --< To add some consistency 
LIMIT 10