Abfragen, die sehr große Datenmengen in PostGIS zurückgeben

8

Ich habe eine PostGIS-Abfrage, die mehrere Millionen Zeilen zurückgibt:

SELECT 
 t1.id AS id1,
 t2.id AS id2,
 ABS(t1.mean_h - t2.mean_h) AS h_diff, 
 ST_Distance(t1.the_geom, t2.the_geom) AS dist  
FROM tas_ponds as t1, tas_ponds as t2 
WHERE
 (t1.gid > t2.gid) AND
 ST_DWithin(t1.the_geom, t2.the_geom, 17000)

Beim Einlaufen psqlerhalte ich eine out of memory for query resultFehlermeldung.

Googeln schlägt vor, dass dies eher ein Fehler in psql als in postgres / PostGIS ist. Würde eine Änderung der Abfrage im Formular SELECT ... INTO x FROM ...das Problem beheben? Gibt es andere empfohlene Ansätze für den Umgang mit sehr großen Datenmengen?

fmark
quelle

Antworten:

7

Einige Stöbern bestätigen, dass es sich um ein Postgres-Client-Problem handelt, unabhängig von räumlichen oder Server-Überlegungen: Der Client verfügt über eine begrenzte Menge an Speicher, um die Ergebnisse zu puffern, bevor sie auf dem Bildschirm angezeigt werden, den Sie überschreiten.

Der empfohlene Ansatz, um dies zu handhaben, besteht darin, einen DECLARE / FETCH- Ansatz zu verwenden, um auf die Daten in kleineren Blöcken als der gesamten Ergebnismenge zuzugreifen. Sie können auch eine Ansicht mit Komponenten der Abfrage (z. B. Entfernung) erstellen, um den für den Abfragevorgang selbst erforderlichen Speicher zu reduzieren.

scw
quelle
5

scw hat mich um zwei Minuten erwischt, also werde ich seine Antwort nicht wiederholen. Hier sind einige andere mögliche Lösungen:

  • Bearbeiten Sie den MemoryAbschnitt von postgresql.conf. Versuchen Sie festzustellen, ob Sie über extrem niedrige Speichereinstellungen verfügen, die möglicherweise die Ausführung der Abfrage verhindern.

  • Versuchen Sie, die Abfrage in eine Datei zu schreiben und über die Befehlszeile auszuführen, indem Sie Folgendes verwenden:

    psql -f Dateiname Datenbankname> Ausgabedatei

  • Wenn Sie die Ergebnisse in einer externen Anwendung verwenden möchten, versuchen Sie, die Abfrage mit einem Cursor von außen auszuführen psql. Zum Beispiel ein Python-Skript, das Ihre Abfrage ausführen würde:

Skript:

try:
    conn = psycopg2.connect("dbname='' user='' host='' password=''") # Fill in
    cur = conn.cursor()
except:
        print 'Unable to connect to the database'
else:
        print 'Connected to database.'

query="""YOUR
         QUERY
         HERE"""
cur.execute(query)

Ein Cursor ist iterierbar, sodass Sie entweder:

for result in cur:
    print result

Oder holen Sie sich alle:

 results=cur.fetchall()
Adam Matan
quelle
2
Ich könnte mich irren, aber ich denke nicht, dass die erste (und vielleicht die zweite) Lösung funktionieren wird. Der erste ändert den Serverspeicher, und dies ist ein Client-Problem, das nicht mit dem verfügbaren Speicher innerhalb des DMBS zusammenhängt, und der zweite würde wahrscheinlich das gleiche Problem haben, es sei denn, nur das Puffern auf dem Bildschirm ist das Problem. Ihre dritte Lösung ist besser als meine IMO, da sie in einer flexiblen Umgebung mit dem Cursor eine fein abgestimmte Steuerung bietet, was in Raw-SQL etwas schwieriger ist. +1
scw
@scw Sie haben wahrscheinlich Recht mit der ersten (und vielleicht zweiten) Lösung. Das Problem ist, dass diese speziellen Tricks manchmal mit PostgreSQL zu funktionieren scheinen, die allgemeine Leistung verbessern und wenig Zeit und Mühe erfordern, um sie auszuprobieren. Ich habe viel aus Ihrer Antwort gelernt.
Adam Matan
2

Für den Datensatz, in meinem Fall das Speichern des zurückgegebenen Datensatzes in einer anderen Tabelle unter Verwendung der SELECT ... INTO ...Syntax funktioniert.

Es löste nicht nur das Problem mit zu wenig Speicher, sondern war auch wesentlich schneller als die ursprüngliche Abfrage.

fmark
quelle
1

Die Indizierung ist in Postgres und PostGIS sehr wichtig

http://postgis.refractions.net/docs/ch04.html#id2794434

Empfehlen Sie GiST-Indizes (Generalized Search Trees) für sehr große Datasets .... (ist auch "null sicher") Beispiel CREATE INDEX [Indexname] ON [Tabellenname] USING GIST ([Geometriefeld]);

Nach dem Erstellen eines Index ist es wichtig, PostgreSQL zu zwingen, Tabellenstatistiken zu sammeln, die zur Optimierung von Abfrageplänen verwendet werden

VACUUM ANALYZE [Tabellenname] [Spaltenname]; SELECT UPDATE_GEOMETRY_STATS ([Tabellenname], [Spaltenname]);

Eine gute Referenz ist auch: Nutzung von Indizes http://postgis.refractions.net/docs/ch04.html#id2794685

Mapperz
quelle
Ja, ich habe die Tabellen indiziert und gesaugt und bestätigt, dass meine Indizes über EXPLAIN usw. verwendet werden. Mein Problem liegt jedoch nicht in der Geschwindigkeit (zu diesem Zeitpunkt), sondern in einem Speicherfehler.
Mark