2012-07-01 5 views
5

Ich habe zwei Tabellen, die ich gerne schneiden würde. Die erste Tabelle repräsentiert etwa 50 Millionen Punkte und die zweite eine Polygonschicht aller Länder der Welt. Ich möchte alle Punkte erhalten, die sich mit diesem Polygon schneiden.Postgresql Spatial Query zu langsam

SELECT d.id, d.geom 
FROM export d, world_boundaries b 
WHERE (b.cntry_name = 'UK') 
    AND d.date_inserted >= '2012-06-01' 
    AND d.geom && b.wkb_geometry 
    AND intersects(d.geom, b.wkb_geometry); 

Diese Abfrage ist sehr einfach, dauert aber mehr als 4 Stunden. Ich habe GIST-Indizes auf der Geometrie-Spalte für jede Tabelle erstellt und VACUUM ANALYSE sie beide. Noch keine Leistungssteigerung. Ich betreibe CENTOS 6 mit Postgres 8.4 und PostGIS 1.5. Kann jemand etwas Licht in die Sache bringen? Ich bekomme sehr schnell Ergebnisse, wenn ich die Abfrage auf 1000 bis 10000 Datensätze LIMITIERE. Wenn ich versuche, das volle Ergebnis zu erfassen, zieht es sich zurück. Gedanken?

UPDATE: Ich sehe jetzt, dass ich meine Abfrage als einen ersten Schritt in diesem Prozess verfeinern muss. Ich bekomme den Umschlag wie folgt

select astext(st_envelope(wkb_geometry)) as e 
from world_borders 
where cntry_name = 'UK' 

Nun, was ist der effizienteste Weg, um dies als Teil der gesamten Abfrage einzuschließen/ausführen?

+1

Jede der letzten Versionen hat die GiST- und GIN-Indizes verbessert. Möglicherweise möchten Sie ein Upgrade auf eine neue Hauptversion in Betracht ziehen. Es könnte sich sogar lohnen, Ihr Problem mit der 9.2 Beta-Version zu versuchen, da es SP-GiST enthält. http://www.postgresql.org/docs/9.2/static/spgist-intro.html – kgrittn

Antwort

1

Versuchen Sie es mit EXPLAIN (und LIMIT) auszuführen, um zu sehen, ob die Indizes überhaupt verwendet werden.

Da die echte Schnittpunktprüfung dort die langsamste Operation ist, würde es vielleicht helfen, sie gegen eine ST_Collect der Unterabfrage (alles außer der ST_Intersects-Prüfung) auszuführen. Auf diese Weise würde es nur einen Aufruf geben, und wenn die Konstruktion der Multigeometrie schnell genug ist, könnte das Nettoergebnis besser sein.

edit1: Nun, stellt sich heraus, es ist nicht so optimal ist, da, wenn Sie die Koordinaten zwingen, bis zu 3d (zu halten, auch die ID), ein extra-Lookup benötigt wird, um die Geometrie-ID zu erhalten:

SELECT d.id, d.geom 
FROM 
(
    SELECT * 
    FROM 
    ( 
     SELECT ST_Collect(d.geom) 
     FROM export d, world_boundaries b 
     WHERE (b.cntry_name = 'UK') 
     AND d.date_inserted >= '2012-06-01' 
     AND d.geom && b.wkb_geometry 
    ) as c, world_boundaries b 
    WHERE (b.cntry_name = 'UK') 
    AND ST_Intersection(c.geom, b.wkb_geometry); 
) as e, export d 
WHERE (ST_Dump(e.geom)).geom = d.geom 
+2

Erwarten Sie nicht, dass der Plan, der mit einer "LIMIT" generiert wird, notwendigerweise dem Plan ohne "LIMIT" ähnelt. Es * könnte * das gleiche sein, aber es könnte völlig anders sein, da der Planer nach dem billigsten Plan sucht, um die angeforderte Anzahl von Zeilen zurückzugeben, eher der billigste Plan zum Zurückgeben aller Zeilen. Diese unterscheiden sich oft. – kgrittn

+0

Gibt es eine Chance, ein Beispiel für die ST_Collect() - Unterabfrage wie bei der obigen SQL-Anweisung zu geben? – aeupinhere

+0

@kgrittn Natürlich, aber ich bezweifle sehr, dass es billiger wäre, dort keinen Index zu verwenden, also sollte es als Diagnose für das, was ich gesagt habe, gut sein. – lynxlynxlynx