Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Lesedauer 6 Min.

Räumliche Daten mit PostGIS in PostgreSQL

Funktionen wie generierte Spalten, LATERAL-Joins und indexbewusste Operatoren ermöglichen in PostGIS räumliche Abfragen, die auch bei zunehmender Komplexität deklarativ, lesbar und performant bleiben.
© EMGenie

Entwickler, die von SQL Server kommen, gehen oft davon aus, dass die räumlichen Funktionen von PostgreSQL mehr oder weniger genauso aussehen und funktionieren wie die von SQL Server. Schließlich bieten beide Systeme Geometrie- und Geografietypen, unterstützen Entfernungsberechnungen und bieten räumliche Indizes. Diese Annahme ist jedoch nur teilweise richtig.

PostgreSQL mit PostGIS deckt zwar alle Funktionen von SQL Server Spatial ab, führt aber auch neue Kompositionskonzepte ein, die SQL Server einfach nicht hat. Das Verständnis dieser Konzepte ist der Schlüssel zur effektiven Nutzung von PostGIS, anstatt nur zu versuchen, SQL-Server-Muster eins zu eins zu replizieren.

Dieser Blogbeitrag führt durch ein kleines, aber vollständiges PostGIS-Beispiel und erklärt, wie jedes Teil dem entspricht, was SQL-Server-Entwickler bereits kennen – und hebt dabei die PostgreSQL-spezifischen Ideen hervor.

Spatial Support als Erweiterung

In SQL Server ist Spatial Support Teil der Engine. Man muss es nie „aktivieren“; Geometrie und Geografie sind immer verfügbar. PostgreSQL verfolgt einen anderen Ansatz. Die Spatial-Funktionalität wird über eine Erweiterung bereitgestellt, die auf dem System vorhanden sein und pro Datenbank aktiviert werden muss:

 

-- Überprüfen, ob die PostGIS-Erweiterung auf dem System installiert ist
 SELECT * FROM pg_available_extensions WHERE name = 'postgis';
 
 -- Erstellen der Erweiterung in der aktuellen Datenbank.
 CREATE EXTENSION IF NOT EXISTS postgis;
 
 -- Überprüfen der PostGIS-Version.
 SELECT postgis_version();

 

Konzeptionell handelt es sich hierbei nicht um eine Einschränkung, sondern um eine Designentscheidung. PostgreSQL hält die Kern-Engine klein und verlagert domänenspezifische Logik in native Erweiterungen. PostGIS ist eines der ausgereiftesten Beispiele für diese Philosophie. Es handelt sich nicht um einen Wrapper oder ein Add-on, sondern um tief integrierten nativen Code.

Für SQL-Server-Entwickler ist es wichtig zu verstehen, dass Funktionen pro Datenbank aktiviert werden können und nicht global gelten.

Geometrie und Geografie: Gleiche Namen, expliziteres Design

Auf den ersten Blick wirkt PostGIS vertraut und beruhigend. Du erhältst weiterhin Geometrie für ebene Berechnungen und Geografie für sphärische, meterbasierte Berechnungen. Der Unterschied wird deutlich, wenn man sich die Beziehung zwischen den beiden ansieht:

 

-- Erstellen einer neuen Tabelle mit den Datentypen GEOMETRY und GEOGRAPHY.
 CREATE TABLE PointOfInterests
 (
     PoiID BIGSERIAL PRIMARY KEY,
     Name TEXT NOT NULL,
     Category TEXT NOT NULL,
     Geom GEOMETRY(POINT, 4326) NOT NULL,
     Geog GEOGRAPHY(POINT, 4326) GENERATED ALWAYS AS (GEOM::GEOGRAPHY) STORED,

     CreatedAt TIMESTAMPTZ NOT NULL DEFAULT NOW()
 );

 

In SQL Server sind GEOMETRY und GEOGRAPHY separate Spalten ohne inhärente Beziehung. Wenn du beide speicherst, liegt es in deiner Verantwortung, sie konsistent zu halten. PostgreSQL ermöglicht es, diese Beziehung mithilfe einer generierten Spalte explizit zu deklarieren. Hier wird Geog immer von Geom abgeleitet. Es kann nicht abweichen, es kann beim Einfügen nicht vergessen werden und es ist per Definition immer korrekt. Dies ist eine kleine Funktion, die jedoch die Sicherheit der Modellierung von räumlichen Daten grundlegend verändert.

Für SQL-Server-Entwickler ebenfalls erwähnenswert:

  • BIGSERIAL ist die Kurzform von PostgreSQL für einen automatisch inkrementierenden BigInt.
  • TIMESTAMPTZ speichert Zeitstempel intern immer in UTC, im Gegensatz zur DateTimeOffset-Semantik von SQL Server.

Einfügen von räumlichen Daten

Das Einfügen von Daten ähnelt stark dem in SQL Server, mit einem wichtigen Unterschied: PostGIS erfordert, dass du SRIDs explizit angibst.

 

-- Einige Points of Interest einfügen
 INSERT INTO PointOfInterests (Name, Category, Geom) VALUES
 ('Stephansdom', 'sight', ST_SetSRID(ST_MakePoint(16.373819, 48.208174), 4326)),
 ('Prater', 'park', ST_SetSRID(ST_MakePoint(16.404954, 48.216778), 4326)),
 ('HBF Wien', 'Bahnhof', ST_SetSRID(ST_MakePoint(16.375000, 48.185000), 4326)),
 ('Schönbrunn', 'Sehenswürdigkeit', ST_SetSRID(ST_MakePoint(16.312222, 48.184516), 4326)),
 ('Donauinsel', 'park', ST_SetSRID(ST_MakePoint(16.410000, 48.240000), 4326));

 

SQL Server lässt dich problemlos räumliche Daten einfügen, ohne die SRID-Konsistenz zu erzwingen. PostGIS behandelt SRIDs als Metadaten erster Klasse und nutzt sie intensiv bei der Validierung, Transformation und Indizierung. Diese Strenge zahlt sich später aus, wenn Abfragen komplexer werden.

Räumliche Indizierung

Bei der Indizierung kommen architektonische Unterschiede zum Tragen.

 

-- Erstellen eines räumlichen Index
 CREATE INDEX poi_geom_gix ON PointOfInterests USING GIST (geom);
 
 -- Aktualisieren der Statistiken
 ANALYZE PointOfInterests;

 

Räumliche Indizes von SQL Server sind gitterbasiert und erfordern eine sorgfältige Konfiguration, um ineffiziente Abfragepläne, die hohe I/O-Last verursachen, zu vermeiden. PostGIS stützt sich auf GiST-Indizes, die sich wie generalisierte R-Bäume verhalten und sich nahtlos in den PostgreSQL-Abfrageplaner integrieren lassen. Der Schritt ANALYZE ist in PostgreSQL explizit. Statistiken werden in Entwicklungsumgebungen nicht immer automatisch aktualisiert, und PostGIS-Abfragen reagieren besonders empfindlich auf Selektivitätsschätzungen.

Entfernungsberechnungen

Entfernungsabfragen unter Verwendung von Geodaten werden dir sofort vertraut sein:

 

-- Entfernungsberechnung zwischen 2 Points of Interest
 SELECT
 
     a.Name AS from_name,

     b.Name AS to_name,

     ST_Distance(a.geog, b.geog) AS distance_m
 FROM PointOfInterests a
 JOIN PointOfInterests b ON a.Name = 'Stephansdom' AND b.Name = 'Schönbrunn';

 

Dies entspricht fast eins zu eins der Funktion STDistance() in SQL Server. Der wichtigste Punkt dabei ist, dass PostGIS nicht versucht zu verbergen, ob du in einem planaren oder sphärischen Raum arbeitest – du wählst dies explizit über den Datentyp aus.

CROSS JOIN LATERAL

Die nächste Abfrage führt etwas ein, das in SQL Server nicht existiert:

 

-- Alle Points of Interest innerhalb eines Radius
 SELECT
     p.PoiID,
     p.Name,
     p.Category,
     ST_Distance(p.Geog, c.Geog) AS distance_m
 FROM PointOfInterests p
 CROSS JOIN LATERAL
 (
      SELECT Geog FROM PointOfInterests WHERE Name = 'Stephansdom'
 ) c
 WHERE ST_DWithin(p.Geog, c.Geog, 4000)
 ORDER BY distance_m;

 

CROSS JOIN LATERAL ermöglicht es einer Unterabfrage, auf Spalten aus der aktuellen Zeile der äußeren Abfrage zu verweisen. In SQL Server würde man dies normalerweise mit Variablen, CTEs oder APPLY simulieren. PostgreSQL macht daraus einen erstklassigen relationalen Operator.

Stelle dir LATERAL als einen Funktionsaufruf pro Zeile vor. Die Unterabfrage wird logischerweise einmal pro äußere Zeile ausgeführt, aber der Planer kann sie aggressiv optimieren. Diese Funktion ermöglicht ausdrucksstarke, komponierbare räumliche Abfragen ohne prozedurale Workarounds.

Suche nach dem nächsten Nachbarn und der Operator <->

Die letzte Abfrage demonstriert eine der leistungsstärksten Funktionen von PostGIS:

 

-- Suche nach dem nächsten Nachbarn
 SELECT 
    p2.PoiID,
    p2.Name,
    p2.Category,
    ST_Distance(p2.geog, ref.geog) AS distance_m
 FROM PointOfInterests p2
 CROSS JOIN (SELECT Geog, Geom FROM PointOfInterests WHERE Name = 'Stephansdom') ref
 WHERE p2.name <> 'Stephansdom'
 ORDER BY p2.Geom <-> ref.Geom
 LIMIT 3;

 

Der Operator <-> führt eine K-Nearest-Neighbor-Sortierung (KNN) unter Verwendung des GiST-Index durch. Dies ist kein Funktionsaufruf, sondern ein Operator, den der Planer genau versteht. SQL Server verfügt über keinen entsprechenden Operator. Nearest-Neighbor-Abfragen erfordern dort in der Regel manuelle Entfernungsberechnungen in Kombination mit TOP und ORDER BY, was oft zu aufwendigen Plänen führt.

In PostGIS ermöglicht <-> es der Datenbank,

  • einen räumlichen Index für die Sortierung zu verwenden,
  • die Berechnung genauer Entfernungen für alle Zeilen zu vermeiden und
  • die nächsten Nachbarn effizient und vorhersehbar zurückzugeben.

 

Dies ist ein grundlegender Unterschied gegenüber SQL Server in der Art und Weise, wie räumliche Abfragen ausgedrückt werden.

Fazit

Für SQL-Server-Entwickler ist PostGIS nicht nur „SQL Server Spatial mit mehr Funktionen“. Es ist ein System, das relationale Kompositionen gegenüber prozeduralen Workarounds bevorzugt. Funktionen wie generierte Spalten, LATERAL-Joins und indexbewusste Operatoren (<->) ermöglichen räumliche Abfragen, die auch bei zunehmender Komplexität deklarativ, lesbar und performant bleiben.

Neueste Beiträge

Window Functions - Acht Kostbarkeiten in T-SQL, Teil 5
Durchblick mit Weitblick: Fensterfunktionen sind nicht nur ein Feature – sie können ein Paradigmenwechsel sein.
6 Minuten
BRIN-Indizes in PostgreSQL - Indizes & Co. in PostgreSQL, Teil 4
PostgreSQL mit BRIN vertritt die Idee, dass ein Index unvollkommen sein kann, solange er kostengünstig und in großem Maßstab effektiv ist. So entsteht eine pragmatische Optimierung, die Präzision gegen Einfachheit eintauscht – und dabei gewinnt.
6 Minuten
SignalRC braucht LTE - Der DDC-Truck, Teil 2
Das LTE-Netz als Transportkanal digitaler Steuerungsdaten bei RC-Modellen.
6 Minuten
28. Jan 2026

Das könnte Dich auch interessieren

GiST- und SP-GiST-Indizes in PostgreSQL - Indizes & Co. in PostgreSQL, Teil 2
GiST ermöglicht es Indizes in PostgreSQL, Beziehungen wie Überschneidung, Einschluss und Entfernung zu verstehen. SP-GiST hingegen erlaubt es Indizes, saubere Partitionen in hierarchischen oder präfixbasierten Daten auszunutzen.
7 Minuten
Partitionierung - Acht Kostbarkeiten in T-SQL, Teil 4
Daten häppchenweise oder: Was ist Partitionierung und warum?
7 Minuten
26. Jan 2026
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige