PostGIS
tillägget som ger PostgreSQL geometri
Vad det är
PostGIS är ett tillägg med öppen källkod till databasservern PostgreSQL. Det låter en kolumn rymma en form, till exempel en leveransadress, en å eller en fastighetsgräns, och låter vanlig SQL räkna ut var formerna ligger i förhållande till varandra. På svenska kallas sådana data oftast geodata eller spatiala data, och en databas med PostGIS en spatial databas. Projektet började som ett forskningsprojekt hos Refractions Research, ett konsultbolag inom GIS och databaser, och utvecklas och släpps i dag som ett eget projekt med öppen källkod.
Det installeras per databas med en enda sats, CREATE EXTENSION postgis;, och tre saker följer
med.
- Spatiala typer.
geometrybeskriver former på ett plant plan, i det koordinatsystem som datan samlades in i.geographybeskriver dem på jordens krökta yta och mäter i meter. - Spatiala funktioner. En stor familj funktioner vars namn börjar med
ST_:ST_IntersectsochST_Containsför samband,ST_AreaochST_Lengthför mätning,ST_Transformför att flytta mellan koordinatsystem ochST_AsGeoJSONför att lämna över resultatet till en webbkarta. - Spatiala index. PostGIS bygger ett R-träd ovanpå PostgreSQL:s GiST-ramverk och stöder också SP-GiST och blockintervallindex (BRIN) för vissa sorters data.
Formerna följer Simple Features, den modell som Open Geospatial Consortium
har publicerat och som har antagits som ISO 19125: punkter, linjer (line strings) och polygoner,
deras flerdelade varianter och samlingar av blandade typer. Varje lagrat värde bär ett SRID, ett
nummer som pekar på en rad i tabellen spatial_ref_sys och talar om vad koordinaterna betyder. SRID
4326 betyder longitud och latitud i grader i referenssystemet WGS 84, det system som GPS rapporterar
i. Ett projicerat system mäter i stället i meter österut och norrut från en fast origo, och det är
exakt bara inom det område det konstruerades för. I Sverige använder tillämpningar på nationell nivå
SWEREF 99 TM, och för lokalt bruk finns tolv lokala projektionszoner.
Rasterdata, topologi och vissa 3D-operationer kommer som separata tillägg, postgis_raster,
postgis_topology och postgis_sfcgal, så att en databas bara bär de delar den faktiskt använder.
Varför det spelar roll
Beslutet som PostGIS tvingar fram är var platsdata ska bo. I en databas utan PostGIS hamnar koordinaterna gärna i två numeriska kolumner, medan det egentliga spatiala arbetet sker någon annanstans: i applikationskod som loopar över rader för att räkna ut avstånd, i ett GIS-program på skrivbordet som någon exporterar till varje måndag, eller i en separat geografisk tjänst med en egen kopia av datan. Varje sådan kopia glider isär. Med PostGIS blir ”vilka kunder ligger inom två kilometer från en depå som har varan i lager” en enda SQL-fråga som kopplar ihop lagersaldon, kundregister och former, inom en och samma transaktion, under samma säkerhetskopior och samma behörigheter som allt annat i databasen.
Det betyder också att spatiala data får samma garantier som resten av databasschemat redan har. Ett CHECK-villkor kan avvisa en ogiltig polygon redan när den skrivs in. Säkerhet på radnivå (row-level security) kan begränsa ett regionalt team till fastigheterna i den egna regionen. En import som fallerar rullas tillbaka i stället för att lämna ett halvt kartskikt efter sig.
Det andra beslutet är geometry eller geography, och PostGIS-manualen är rak på den punkten. Data
som håller sig inom en stad eller ett land lagras oftast bäst som geometry i en projektion vald
för området, eftersom hela funktionsuppsättningen finns och aritmetiken är snabb. Data som spänner
över kontinenter, eller vars användare vill ha avstånd i meter mellan punkter var som helst på
jorden, är lättare att få rätt som geography. Den typen sköter själv matematiken på den krökta
ytan, till priset av en mindre uppsättning funktioner.
Och ibland är svaret att PostGIS är mer än jobbet kräver. En app som bara lagrar latitud och longitud per butik och sätter ut nålar på en karta klarar sig med två numeriska kolumner. PostGIS gör sig förtjänt av sin plats när det du behöver veta gäller avstånd, inneslutning eller överlappning, eller när datan innehåller linjer och polygoner snarare än enstaka punkter.
Så ser det ut i praktiken
PostGIS var skälet till ett databasbyte i det ena projektet och arbetshästen under en upprensning i det andra.
En kartapplikation som besvarade spatiala databasfrågor i realtid för många användare körde på en Microsoft SQL Server-databas utan inbyggd geospatial indexering, och latensen gick ut över både kartan och tjänsterna bakom den. Lösningen blev en flytt till PostgreSQL med PostGIS, med ett schema utformat för spatiala data, GiST- och SP-GiST-index på geometri- och geografikolumnerna och villkor på de spatiala koordinaterna. Över 50 miljoner spatiala poster gick genom ETL-pipelines som transformerade dem till EPSG:4326 på vägen in. Efter flytten tog ett genomsnittligt svar under 250 millisekunder i stället för 2,5 sekunder, de spatiala frågorna presterade 10 gånger bättre och backenden använde 65 % mindre CPU.
Det andra projektet började med data snarare än hastighet. Ett stort geospatialt analysprojekt hittade över 1 000 inkonsekvenser i geografiska dataset och tidsseriedataset. GDAL, QGIS och ArcGIS användes för att hitta och rätta de spatiala felen, medan PostGIS körde de spatiala databasfrågorna och den spatiala indexeringen, med procedurer i PL/pgSQL som transformerade datan inne i PostgreSQL, och det rensade resultatet visades i Mapbox. Körtiderna för spatiala SQL-frågor sjönk med 35 %.
Var det går fel
Avstånd kommer tillbaka som pyttesmå decimaltal. En SQL-fråga ber om avståndet mellan två orter
och får 0.08. Kolumnen är geometry i SRID 4326, så svaret är i grader, och en längdgrad krymper
från ca 111 kilometer vid ekvatorn till ingenting vid polerna. Konvertera till geography för att
få svaret i meter, eller flytta datan med ST_Transform till ett projicerat system som passar
området innan du mäter.
En radiesökning läser varenda rad. Tabellen har ett spatialt index, men planen visar en
sekventiell skanning. Den vanliga orsaken är ett filter skrivet som ST_Distance(a, b) < 500.
Manualens lista över funktioner som använder indexet av sig själva tar med ST_DWithin men inte
ST_Distance. Att linda in den indexerade kolumnen i en typkonvertering eller en transformering
har samma effekt, eftersom ett index på geom inte säger någonting om geom::geography.
-- en geography-kolumn, indexerad som den lagras, mätt i meter
CREATE INDEX depots_geog_idx ON depots USING GIST (geog);
SELECT id FROM depots
WHERE ST_DWithin(geog, ST_MakePoint(12.57, 55.68)::geography, 500);
Om datan måste stanna i en geometry-kolumn i 4326 kan du antingen lägga till en
geography-kolumn som den här och indexera den, eller skapa indexet på samma uttryck som SQL-frågan
använder. Kör ANALYZE efter en massinläsning, så att planeraren vet att indexet är värt att ta.
Punkterna hamnar i havet. Varje form behåller sitt mönster men ligger på fel plats, ofta på en
annan kontinent. Två misstag ger det här. ST_SetSRID märker bara om en geometri och låter dess
tal vara som de är, så om den används där ST_Transform var avsedd stämplas meter som grader. Det
andra är att longitud och latitud har bytt plats någonstans uppströms: PostGIS förväntar sig,
precis som GeoJSON, x före y, alltså longitud före latitud. Använd ST_SetSRID bara för att
deklarera vad talen redan är och ST_Transform för att räkna om dem, och testa varje import med en
punkt vars läge du känner till.
Area- och överlappsberäkningar kastar fel. En import från en shapefil går igenom, och senare
fallerar ST_Intersection med ett topologiundantag. PostGIS lagrar ogiltig geometri med avsikt, så
att den kan hittas och lagas, och en polygon vars gräns korsar sig själv är ogiltig. Kontrollera
med ST_IsValid, laga med ST_MakeValid, som behåller varenda ursprunglig hörnpunkt, och lägg
till ett CHECK-villkor så att en dålig form avvisas redan i dörren i stället för att upptäckas i en
rapport.
Läs mer
- PostGIS Documentation — projektets egen ingång till manualen, FAQ:n och utbildningsmaterialet.
- Data Management — geometry och geography, SRID, giltighetsregler och de tre indextyperna, så som manualen definierar dem.
- Spatial Indexing — workshopens kapitel om omslutande rektanglar och om de funktioner som använder ett index utan att bli tillsagda.
- ST_DWithin — referenssidan för avståndstestet, med enheterna för varje typ.
- Simple Feature Access – Part 1 — OGC-standarden bakom de geometrityper som PostGIS lagrar.
- SWEREF 99, projektioner — Lantmäteriets beskrivning av SWEREF 99 TM och de tolv lokala projektionszonerna.