Hoppa till innehållet

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. geometry beskriver former på ett plant plan, i det koordinatsystem som datan samlades in i. geography beskriver dem på jordens krökta yta och mäter i meter.
  • Spatiala funktioner. En stor familj funktioner vars namn börjar med ST_: ST_Intersects och ST_Contains för samband, ST_Area och ST_Length för mätning, ST_Transform för att flytta mellan koordinatsystem och ST_AsGeoJSON fö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.

Ordlista