Open Geospatial Consortium (OGC) har utvecklat Enkel åtkomst till funktioner (SFA) för att tillhandahålla en modell för geospatiala data. Den definierar den grundläggande spatiala typen av geometri, tillsammans med operationer som manipulerar och transformerar geometrivärden för att utföra spatiala analysuppgifter. PostGIS implementerar OGC Geometry-modellen som PostgreSQL-datatyperna geometri och geografi.
Geometry är en abstrakt typ. Geometry-värden tillhör en av dess konkreta subtyper som representerar olika typer och dimensioner av geometriska former. Dessa inkluderar atomtyperna Point, LineString, LinearRing och Polygon, samt samlingstyperna MultiPoint, MultiLineString, MultiPolygon och GeometryCollection. De Access till enkla funktioner - Del 1: Gemensam arkitektur v1.2.1 lägger till subtyper för strukturerna PolyhedralSurface, Triangle och TIN.
Geometry modellerar former i det 2-dimensionella kartesiska planet. Typerna PolyhedralSurface, Triangle och TIN kan också representera former i ett 3-dimensionellt rum. Formernas storlek och placering anges av deras koordinater. Varje koordinat har ett X- och Y-ordinatvärde som bestämmer dess läge i planet. Former konstrueras av punkter eller linjesegment, där punkter specificeras av en enda koordinat och linjesegment av två koordinater.
Koordinaterna kan innehålla valfria Z- och M-ordinatvärden. Z-ordinaten används ofta för att representera höjd. M-ordinaten innehåller ett mätvärde, som kan representera tid eller avstånd. Om Z- eller M-värden finns i ett geometrivärde måste de definieras för varje punkt i geometrin. Om en geometri har Z- eller M-ordinater är koordinatdimensionen 3D; om den har både Z- och M-ordinater är koordinatdimensionen 4D.
Geometrivärden associeras med ett spatialt referenssystem som anger det koordinatsystem i vilket det är inbäddat. Det spatiala referenssystemet identifieras av geometrins SRID-nummer. Enheterna för X- och Y-axlarna bestäms av det spatiala referenssystemet. I plana referenssystem representerar X- och Y-koordinaterna vanligtvis ost- och nordlig riktning, medan de i geodetiska system representerar longitud och latitud. SRID 0 representerar ett oändligt kartesiskt plan utan några enheter tilldelade dess axlar. Se Section 4.5, “Spatiala referenssystem”.
Geometridimensionen är en egenskap hos geometrityper. Punkttyper har dimension 0, linjära typer har dimension 1 och polygonala typer har dimension 2. Samlingar har dimensionen för den maximala elementdimensionen.
Ett geometrivärde kan vara tomt. Tomma värden innehåller inga toppar (för atomära geometrityper) eller inga element (för samlingar).
En viktig egenskap hos geometrivärden är deras spatiala extent eller bounding box, som i OGC-modellen kallas envelope. Detta är den 2- eller 3-dimensionella box som omsluter koordinaterna för en geometri. Det är ett effektivt sätt att representera en geometris utbredning i koordinatrymden och att kontrollera om två geometrier interagerar.
Geometrimodellen gör det möjligt att utvärdera topologiska spatiala relationer enligt beskrivningen i Section 5.1.1, “Dimensionsutvidgad 9-intersektionell modell”. För att stödja detta definieras begreppen interior, boundary och exterior för varje geometrityp. Geometrier är topologiskt slutna, vilket innebär att de alltid innehåller sin gräns. Gränsen är en geometri med en dimension som är en mindre än geometrins egen dimension.
OGC:s geometrimodell definierar giltighetsregler för varje geometrityp. Dessa regler säkerställer att geometrivärdena representerar realistiska situationer (det är t.ex. möjligt att ange en polygon med ett hål som ligger utanför skalet, men detta är geometriskt ologiskt och därmed ogiltigt). PostGIS tillåter också lagring och manipulering av ogiltiga geometrivärden. Detta gör det möjligt att upptäcka och åtgärda dem vid behov. Se även Section 4.4, “Validering av geometri”
En punkt är en 0-dimensionell geometri som representerar en enda plats i koordinatrymden.
POINT (1 2) POINT Z (1 2 3) POINT ZM (1 2 3 4)
En LineString är en 1-dimensionell linje som består av en sammanhängande sekvens av linjesegment. Varje linjesegment definieras av två punkter, där slutpunkten för ett segment utgör startpunkten för nästa segment. En OGC-valid LineString har antingen noll eller två eller flera punkter, men PostGIS tillåter även LineStrings med en enda punkt. LineStrings kan korsa sig själva (self-intersect). En LineString är sluten om start- och slutpunkterna är desamma. En LineString är enkel om den inte korsar sig själv.
LINESTRING (1 2, 3 4, 5 6)
En LinearRing är en LineString som är både sluten och enkel. Den första och den sista punkten måste vara lika och linjen får inte skära sig själv.
LINEARRING (0 0 0, 4 0 0, 4 4 0, 0 4 0, 0 0 0)
En polygon är en 2-dimensionell plan region som avgränsas av en yttre gräns (skalet) och noll eller flera inre gränser (hål). Varje gräns är en LinearRing.
POLYGON ((0 0 0,4 0 0,4 4 0,0 4 0,0 0 0),(1 1 0,2 1 0,2 2 0,1 2 0,1 1 0))
En MultiPoint är en samling punkter.
MULTIPOINT ( (0 0), (1 2) )
En MultiLineString är en samling LineStrings. En MultiLineString är sluten om vart och ett av dess element är slutet.
MULTILINESTRING ( (0 0,1 1,1 2), (2 3,3 2,5 4) )
En MultiPolygon är en samling polygoner som inte överlappar varandra och inte ligger intill varandra. Polygonerna i samlingen får endast beröra varandra i ett begränsat antal punkter.
MULTIPOLYGON (((1 5, 5 5, 5 1, 1 1, 1 5)), ((6 5, 9 1, 6 1, 6 5)))
En GeometryCollection är en heterogen (blandad) samling av geometrier.
GEOMETRYCOLLECTION ( POINT(2 3), LINESTRING(2 3, 3 4))
En PolyhedralSurface är en sammanhängande samling av patcher eller facetter som delar vissa kanter. Varje patch är en plan polygon. Om polygonens koordinater har Z-ordinater är ytan 3-dimensionell.
POLYHEDRALSURFACE Z ( ((0 0 0, 0 0 1, 0 1 1, 0 1 0, 0 0 0)), ((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)), ((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)), ((1 1 0, 1 1 1, 1 0 1, 1 0 0, 1 1 0)), ((0 1 0, 0 1 1, 1 1 1, 1 1 0, 0 1 0)), ((0 0 1, 1 0 1, 1 1 1, 0 1 1, 0 0 1)) )
En triangel är en polygon som definieras av tre distinkta, icke-kollinjära hörn. Eftersom en triangel är en polygon anges den med fyra koordinater, där den första och den fjärde är lika.
TRIANGLE ((0 0, 0 9, 9 0, 0 0))
En TIN är en samling icke-överlappande trianglarsom representerar ett triangulerat oregelbundet nätverk.
TIN Z ( ((0 0 0, 0 0 1, 0 1 0, 0 0 0)), ((0 0 0, 0 1 0, 1 1 0, 0 0 0)) )
ISO/IEC 13249-3 ISO/IEC 13249-3 SQL Multimedia - Spatial (SQL/MM) utökar OGC SFA för att definiera Geometry-subtyper som innehåller kurvor med cirkelbågar. SQL/MM-typerna stöder 3DM-, 3DZ- och 4D-koordinater.
![]() |
|
Alla jämförelser med flyttal i SQL-MM-implementationen utförs med en angiven tolerans, för närvarande 1E-8. |
CircularString är den grundläggande kurvtypen, ungefär som LineString i den linjära världen. Ett enkelt bågsegment specificeras av tre punkter: start- och slutpunkterna (första och tredje) samt någon annan punkt på bågen. För att specificera en sluten cirkel är start- och slutpunkterna desamma och mittpunkten är den motsatta punkten på cirkeldiametern (som är bågens mittpunkt). I en sekvens av bågar är slutpunkten för den föregående bågen startpunkten för nästa båge, precis som segmenten i en LineString. Detta innebär att en CircularString måste ha ett udda antal punkter som är större än 1.
CIRCULARSTRING(0 0, 1 1, 1 0) CIRCULARSTRING(0 0, 4 0, 4 4, 0 4, 0 0)
En CompoundCurve är en enda kontinuerlig kurva som kan innehålla både cirkelbågssegment och linjära segment. Det innebär att förutom att ha välformade komponenter måste slutpunkten för varje komponent (utom den sista) sammanfalla med startpunkten för följande komponent.
COMPOUNDCURVE( CIRCULARSTRING(0 0, 1 1, 1 0),(1 0, 0 1))
En CurvePolygon är som en polygon, med en yttre ring och noll eller flera inre ringar. Skillnaden är att en ring kan vara en CircularString eller CompoundCurve såväl som en LineString.
Från och med PostGIS 1.4 har PostGIS stöd för sammansatta kurvor i en kurvpolygon.
CURVEPOLYGON( CIRCULARSTRING(0 0, 4 0, 4 4, 0 4, 0 0), (1 1, 3 3, 3 1, 1 1) )
Exempel: En CurvePolygon med skalet definierat av en CompoundCurve som innehåller en CircularString och en LineString, och ett hål definierat av en CircularString
CURVEPOLYGON( COMPOUNDCURVE( CIRCULARSTRING(0 0,2 0, 2 1, 2 3, 4 3), (4 3, 4 5, 1 4, 0 0)), CIRCULARSTRING(1.7 1, 1.4 0.4, 1.6 0.4, 1.6 0.5, 1.7 1) )
En MultiCurve är en samling kurvor som kan innehålla LineStrings, CircularStrings eller CompoundCurves.
MULTICURVE( (0 0, 5 5), CIRCULARSTRING(4 0, 4 4, 8 4))
En MultiSurface är en samling ytor, som kan vara (linjära) polygoner eller CurvePolygoner.
MULTISURFACE( CURVEPOLYGON( CIRCULARSTRING( 0 0, 4 0, 4 4, 0 4, 0 0), (1 1, 3 3, 3 1, 1 1)), ((10 10, 14 12, 11 10, 10 10), (11 11, 11.5 11, 11 11.5, 11 11)))
OGC SFA-specifikationen definierar två format för att representera geometriska värden för extern användning: Well-Known Text (WKT) och Well-Known Binary (WKB). Både WKT och WKB innehåller information om typen av objekt och de koordinater som definierar det.
Well-Known Text (WKT) tillhandahåller en standardiserad textuell representation av spatiala data. Exempel på WKT-representationer av spatiala objekt är:
PUNKT(0 0)
PUNKT Z (0 0 0)
PUNKT ZM (0 0 0 0)
PUNKT EMPTY
LINESTRING(0 0,1 1,1 2)
LINESTRING TOM
POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1))
MULTIPOINT((0 0),(1 2))
MULTIPOINT Z ((0 0 0),(1 2 3))
MULTIPOINT TOM
MULTILINESTRING((0 0,1 1,1 2),(2 3,3 2,5 4))
MULTIPOLYGON(((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1)), ((-1 -1,-1 -2,-2 -2,-2 -1,-1 -1 -1)))
GEOMETRYCOLLECTION(PUNKT(2 3),LINESTRING(2 3,3 4))
GEOMETRYUPPCOLLECTION TOM
In- och utdata för WKT tillhandahålls av funktionerna ST_AsText och ST_GeomFromText:
text WKT = ST_AsText(geometry); geometry = ST_GeomFromText(text WKT, SRID);
Ett exempel på en instruktion för att skapa och infoga ett spatialt objekt från WKT och en SRID är:
INSERT INTO geotable ( geom, name ) VALUES ( ST_GeomFromText('POINT(-126.4 45.32)', 312), 'A Place');
Well-Known Binary (WKB) tillhandahåller en portabel representation med full precision av spatiala data som binära data (matriser av bytes). Exempel på WKB-representationer av spatiala objekt är:
WKT: PUNKT(1 1)
WKB: 0101000000000000000000F03F000000000000F03
WKT: LINESTRING (2 2, 9 9)
WKB: 0102000000020000000000000000000040000000000000004000000000000022400000000000002240
In- och utdata för WKB tillhandahålls av funktionerna ST_AsBinary och ST_GeomFromWKB:
bytea WKB = ST_AsBinary(geometry); geometry = ST_GeomFromWKB(bytea WKB, SRID);
Ett villkor för att skapa och infoga ett spatialt objekt från WKB är t.ex:
INSERT INTO geotable ( geom, name ) VALUES ( ST_GeomFromWKB('\x0101000000000000000000f03f000000000000f03f', 312), 'A Place');
PostGIS implementerar OGC Simple Features-modellen genom att definiera en PostgreSQL-datatyp som heter geometry
. Den representerar alla undertyper av geometri med hjälp av en intern typkod (se GeometryType och ST_GeometryType). Detta gör det möjligt att modellera spatiala funktioner som rader i tabeller som definieras med en kolumn av typen geometri
.
Datatypen geometry
är opak, vilket innebär att all åtkomst sker genom att funktioner anropas på geometrivärden. Funktionerna gör det möjligt att skapa geometriobjekt, komma åt eller uppdatera alla interna fält och beräkna nya geometrivärden. PostGIS stöder alla funktioner som anges i OGC:s Enkel åtkomst till funktioner - Del 2: SQL-alternativ (SFS)-specifikationen, samt många andra. Se Chapter 7, PostGIS-referens för en fullständig lista över funktioner.
![]() |
|
PostGIS följer SFA-standarden genom att spatiala funktioner prefixeras med "ST_". Detta var tänkt att stå för "Spatial and Temporal", men den temporala delen av standarden utvecklades aldrig. Istället kan det tolkas som "Spatial Type". |
SFA-standarden anger att spatiala objekt ska innehålla en identifierare för spatialt referenssystem (Spatial Reference System identifier, SRID). SRID krävs när spatiala objekt skapas för införande i databasen (den kan vara 0 som standard). Se ST_SRID och Section 4.5, “Spatiala referenssystem”
För att göra geometriska frågor effektiva definierar PostGIS olika typer av spatiala index och spatiala operatorer för att använda dem. Se Section 4.9, “Spatiala index” och Section 5.2, “Använda spatiala index” för mer information.
OGC SFA-specifikationerna stödde ursprungligen endast 2D-geometrier, och geometrins SRID ingår inte i inmatnings-/utdatarepresentationerna. OGC SFA-specifikationen 1.2.1 (som överensstämmer med ISO 19125-standarden) lägger till stöd för 3D (ZYZ) och uppmätta (XYM och XYZM) koordinater, men inkluderar fortfarande inte SRID-värdet.
På grund av dessa begränsningar har PostGIS definierat utökade EWKB- och EWKT-format. De ger stöd för koordinater i 3D (XYZ och XYM) och 4D (XYZM) och inkluderar SRID-information. Genom att inkludera all geometriinformation kan PostGIS använda EWKB som format för registrering (t.ex. i DUMP-filer).
EWKB och EWKT används för de "kanoniska formerna" för PostGIS dataobjekt. För indata är den kanoniska formen för binära data EWKB, och för textdata accepteras antingen EWKB eller EWKT. Detta gör det möjligt att skapa geometrivärden genom att kasta ett textvärde i antingen HEXEWKB eller EWKT till ett geometrivärde med hjälp av ::geometry
. För utdata är den kanoniska formen för binära data EWKB och för text är den HEXEWKB (hex-kodad EWKB).
Till exempel skapar denna sats en geometri genom casting från ett EWKT-textvärde och matar ut den med den kanoniska formen av HEXEWKB:
SELECT 'SRID=4;POINT(0 0)'::geometry; geometry ---------------------------------------------------- 01010000200400000000000000000000000000000000000000
PostGIS EWKT-utdata har några skillnader jämfört med OGC WKT:
För 3DZ-geometrier utelämnas Z-kvalificeraren:
OGC: PUNKT Z (1 2 3)
EWKT: PUNKT (1 2 3)
För 3DM-geometrier inkluderas M-kvalificeraren:
OGC: PUNKT M (1 2 3)
EWKT: POINTM (1 2 3)
För 4D-geometrier utelämnas ZM-kvalificeraren:
OGC: PUNKT ZM (1 2 3 4)
EWKT: PUNKT (1 2 3 4)
EWKT undviker överspecificering av dimensionalitet och de inkonsekvenser som kan uppstå med OGC/ISO-formatet, t.ex:
POINT ZM (1 1)
PUNKT ZM (1 1 1)
PUNKT (1 1 1 1 1)
![]() |
|
PostGIS utökade format är för närvarande en superset av OGC:s format, så att varje giltig OGC WKB/WKT också är giltig EWKB/EWKT. Detta kan dock variera i framtiden, om OGC utökar ett format på ett sätt som strider mot PosGIS-definitionen. Därför SKA du INTE förlita dig på denna kompatibilitet! |
Exempel på EWKT-textrepresentation av spatiala objekt är:
PUNKT(0 0 0) -- XYZ
SRID=32632;POINT(0 0) -- XY med SRID
POINTM(0 0 0) -- XYM
PUNKT(0 0 0 0) -- XYZM
SRID=4326;MULTIPOINTM(0 0 0,1 2 1) -- XYM med SRID
MULTILINESTRING((0 0 0,1 1 0,1 2 1),(2 3 1,3 2 1,5 4 1))
POLYGON((0 0 0,4 0 0,4 4 0,0 4 0,0 0 0),(1 1 0,2 1 0,2 2 0,1 2 0,1 1 0))
MULTIPOLYGON(((0 0 0,4 0 0,4 4 0,0 4 0,0 0 0),(1 1 0,2 1 0,2 2 0,1 2 0,1 1 0)),((-1 -1 0,-1 -2 0,-2 -2 0,-2 -1 0,-1 -1 0)))
GEOMETRYCOLLECTIONM( PUNKTM(2 3 9), LINESTRINGM(2 3 4, 3 4 5) )
MULTICURVE( (0 0, 5 5), CIRCULARSTRING(4 0, 4 4, 8 4) )
POLYHEDRALSURFACE( ((0 0 0, 0 0 1, 0 1 1, 0 1 0, 0 0 0)), ((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)), ((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)), ((1 1 0, 1 1 1, 1 0 1, 1 0 0, 1 1 0)), ((0 1 0, 0 1 1, 1 1 1, 1 1 0, 0 1 0)), ((0 0 1, 1 0 1, 1 1 1, 0 1 1, 0 0 1)) )
TRIANGEL ((0 0, 0 10, 10 0, 0 0))
TIN( ((0 0 0, 0 0 1, 0 1 0, 0 0 0)), ((0 0 0, 0 1 0, 1 1 0, 0 0 0))) )
Inmatning och utdata med dessa format kan göras med hjälp av följande funktioner:
bytea EWKB = ST_AsEWKB(geometry); text EWKT = ST_AsEWKT(geometry); geometry = ST_GeomFromEWKB(bytea EWKB); geometry = ST_GeomFromEWKT(text EWKT);
Ett villkor för att skapa och infoga ett spatialt PostGIS-objekt med EWKT är t.ex:
INSERT INTO geotable ( geom, name ) VALUES ( ST_GeomFromEWKT('SRID=312;POINTM(-126.4 45.32 15)'), 'A Place' )
Datatypen PostGIS geography
ger inbyggt stöd för spatiala egenskaper som representeras av "geografiska" koordinater (ibland kallade "geodetiska" koordinater, eller "lat/lon", eller "lon/lat"). Geografiska koordinater är sfäriska koordinater uttryckta i vinkelenheter (grader).
Basen för PostGIS datatyp geometri är ett plan. Den kortaste vägen mellan två punkter på planet är en rät linje. Det innebär att funktioner på geometrier (ytor, avstånd, längder, skärningspunkter etc.) beräknas med hjälp av rätlinjiga vektorer och kartesisk matematik. Detta gör dem enklare att implementera och snabbare att utföra, men gör dem också felaktiga för data på jordens sfäroida yta.
PostGIS datatyp för geografi är baserad på en sfärisk modell. Den kortaste vägen mellan två punkter på sfären är en storcirkelbåge. Funktioner på geografier (områden, avstånd, längder, skärningspunkter etc.) beräknas med hjälp av bågar på sfären. Genom att ta hänsyn till världens sfäroida form ger funktionerna mer exakta resultat.
Eftersom den underliggande matematiken är mer komplicerad finns det färre funktioner definierade för geograftypen än för geometritypen. Med tiden, när nya algoritmer läggs till, kommer funktionerna för geograftypen att utökas. Som en nödlösning kan man konvertera fram och tillbaka mellan geometri- och geograftyperna.
I likhet med datatypen geometri associeras geografiska data med ett spatialt referenssystem via en identifierare för spatialt referenssystem (SRID). Alla geodetiska (längd/lat-baserade) spatiala referenssystem som definieras i tabellen spatial_ref_sys
kan användas. (Före PostGIS 2.2 stödde geografin endast geodetisk WGS 84 (SRID:4326)). Du kan lägga till ditt eget anpassade geodetiska spatiala referenssystem enligt beskrivningen i Section 4.5.2, “Användardefinierade spatiala referenssystem”.
För alla spatiala referenssystem är de enheter som returneras av mätfunktioner (t.ex. ST_Distance, ST_Length, ST_Perimeter, ST_Area) och för distansargumentet i ST_DWithin i meter.
Du kan skapa en tabell för att lagra geografiska data genom att använda SQL-satsen CREATE TABLE med en kolumn av typen geography
. I följande exempel skapas en tabell med en geografikolumn som lagrar 2D LineStrings i det geodetiska koordinatsystemet WGS84 (SRID 4326):
CREATE TABLE global_points ( id SERIAL PRIMARY KEY, name VARCHAR(64), location geography(POINT,4326) );
Geografitypen har stöd för två valfria typmodifierare:
modifieraren spatial type begränsar vilka typer av former och dimensioner som tillåts i kolumnen. Tillåtna värden för den spatiala typen är: POINT, LINESTRING, POLYGON, MULTIPOINT, MULTILINESTRING, MULTIPOLYGON, GEOMETRYCOLLECTION. Geografitypen stöder inte kurvor, TINS eller POLYHEDRALSURFACEs. Modifieraren stöder begränsningar av koordinatdimensionalitet genom att lägga till suffix: Z, M och ZM. En modifierare av typen "LINESTRINGM" tillåter t.ex. endast linestrings med tre dimensioner och behandlar den tredje dimensionen som ett mått. På samma sätt kräver "POINTZM" fyrdimensionella (XYZM) data.
sRID-modifieraren begränsar det spatiala referenssystemets SRID till ett visst nummer. Om SRID utelämnas är standardvärdet 4326 (WGS84 geodetic) och alla beräkningar utförs med WGS84.
Exempel på hur man skapar tabeller med geografikolumner:
Skapa en tabell med 2D POINT-geografi med standard SRID 4326 (WGS84 long/lat):
CREATE TABLE ptgeogwgs(gid serial PRIMARY KEY, geog geography(POINT) );
Skapa en tabell med 2D POINT-geografi i NAD83 longlat:
CREATE TABLE ptgeognad83(gid serial PRIMARY KEY, geog geography(POINT,4269) );
Skapa en tabell med 3D (XYZ) POINTs och en explicit SRID på 4326:
CREATE TABLE ptzgeogwgs84(gid serial PRIMARY KEY, geog geography(POINTZ,4326) );
Skapa en tabell med 2D LINESTRING-geografi med standard SRID 4326:
CREATE TABLE lgeog(gid serial PRIMARY KEY, geog geography(LINESTRING) );
Skapa en tabell med 2D POLYGON-geografi med SRID 4267 (NAD 1927 long lat):
CREATE TABLE lgeognad27(gid serial PRIMARY KEY, geog geography(POLYGON,4267) );
Geografiska fält registreras i systemvyn geography_columns
. Du kan ställa en fråga till vyn geography_columns
och se att tabellen finns med i listan:
SELECT * FROM geography_columns;
Att skapa ett spatialt index fungerar på samma sätt som för geometrikolumner. PostGIS kommer att notera att kolumntypen är GEOGRAPHY och skapa ett lämpligt sfärbaserat index istället för det vanliga plana indexet som används för GEOMETRY.
-- Index the test table with a spherical index CREATE INDEX global_points_gix ON global_points USING GIST ( location );
Du kan infoga data i geograftabeller på samma sätt som i geometritabeller. Geometridata kommer att autokastas till geograftypen om den har SRID 4326. EWKT- och EWKB-formaten kan också användas för att ange geografiska värden.
-- Add some data into the test table INSERT INTO global_points (name, location) VALUES ('Town', 'SRID=4326;POINT(-110 30)'); INSERT INTO global_points (name, location) VALUES ('Forest', 'SRID=4326;POINT(-109 29)'); INSERT INTO global_points (name, location) VALUES ('London', 'SRID=4326;POINT(0 49)');
Alla geodetiska (lång/lat) spatiala referenssystem som förtecknas i tabellen spatial_ref_sys
kan anges som ett geografiskt SRID. Icke-geodetiska koordinatsystem ger upphov till ett fel om de används.
-- NAD 83 lon/lat SELECT 'SRID=4269;POINT(-123 34)'::geography; geography ---------------------------------------------------- 0101000020AD1000000000000000C05EC00000000000004140
-- NAD27 lon/lat SELECT 'SRID=4267;POINT(-123 34)'::geography; geography ---------------------------------------------------- 0101000020AB1000000000000000C05EC00000000000004140
-- NAD83 UTM zone meters - gives an error since it is a meter-based planar projection SELECT 'SRID=26910;POINT(-123 34)'::geography; ERROR: Only lon/lat coordinate systems are supported in geography.
Fråge- och mätfunktioner använder enheter i meter. Avståndsparametrar bör därför uttryckas i meter och returvärden bör förväntas i meter (eller kvadratmeter för områden).
-- A distance query using a 1000km tolerance SELECT name FROM global_points WHERE ST_DWithin(location, 'SRID=4326;POINT(-110 29)'::geography, 1000000);
Du kan se geografins kraft i aktion genom att beräkna hur nära ett plan som flyger en cirkelrutt från Seattle till London (LINESTRING(-122,33 47,606, 0,0 51,5)) kommer Reykjavik (POINT(-21,96 64,15))(kartlägg rutten).
Geografitypen beräknar det kortaste verkliga avståndet på 122,235 km över sfären mellan Reykjavik och storcirkelflygvägen mellan Seattle och London.
-- Distance calculation using GEOGRAPHY SELECT ST_Distance('LINESTRING(-122.33 47.606, 0.0 51.5)'::geography, 'POINT(-21.96 64.15)'::geography); st_distance ----------------- 122235.23815667
Geometritypen beräknar ett meningslöst kartesiskt avstånd mellan Reykjavik och den raka vägen från Seattle till London utritad på en platt världskarta. Den nominella enheten för resultatet är "grader", men resultatet motsvarar inte någon verklig vinkelskillnad mellan punkterna, så att kalla dem "grader" är felaktigt.
-- Distance calculation using GEOMETRY SELECT ST_Distance('LINESTRING(-122.33 47.606, 0.0 51.5)'::geometry, 'POINT(-21.96 64.15)'::geometry); st_distance -------------------- 13.342271221453624
Med datatypen Geography kan du lagra data i koordinater för longitud/latitud, men till en kostnad: det finns färre funktioner definierade för GEOGRAPHY än för GEOMETRY; de funktioner som är definierade tar mer CPU-tid att utföra.
Den datatyp du väljer bör bestämmas av det förväntade arbetsområdet för den applikation du bygger. Kommer dina data att omfatta hela jordklotet eller ett stort kontinentalt område, eller är de lokala för en stat, ett län eller en kommun?
Om dina data finns i ett litet område kan det hända att du tycker att det är bäst att välja en lämplig projektion och använda GEOMETRY, med tanke på prestanda och tillgängliga funktioner.
Om dina data är globala eller täcker en kontinental region kanske du tycker att GEOGRAPHY gör att du kan bygga ett system utan att behöva oroa dig för projektionsdetaljer. Du lagrar dina data i longitud/latitud och använder de funktioner som har definierats i GEOGRAPHY.
Om du inte förstår projektioner, inte vill lära dig mer om dem och är beredd att acceptera de begränsningar i funktionalitet som finns i GEOGRAPHY, kan det vara lättare för dig att använda GEOGRAPHY än GEOMETRY. Läs in helt enkelt upp dina data som longitud/latitud och fortsätt därifrån.
Se Section 13.11, “PostGIS matris för funktionsstöd” för en jämförelse mellan vad som stöds för Geography respektive Geometry. För en kort lista och beskrivning av Geography-funktioner, se Section 13.4, “Stödfunktioner för geografi i PostGIS”
4.3.4.1. |
Räknar du på sfären eller sfäroiden? |
Som standard görs alla avstånds- och områdesberäkningar på sfäroiden. Du bör upptäcka att resultaten av beräkningar i lokala områden stämmer väl överens med lokala plana resultat i bra lokala projektioner. Över större områden kommer sfäroidberäkningarna att vara mer exakta än alla beräkningar som görs på ett projicerat plan. Alla geografifunktioner har möjlighet att använda en sfärberäkning genom att ställa in en sista boolesk parameter till "FALSE". Detta snabbar upp beräkningarna något, särskilt i fall där geometrierna är mycket enkla. |
|
4.3.4.2. |
Hur är det med datumlinjen och polerna? |
Alla beräkningar har ingen uppfattning om datumlinje eller poler, koordinaterna är sfäriska (longitud/latitud) så en form som korsar datumlinjen är, ur en beräkningssynpunkt, inte annorlunda än någon annan form. |
|
4.3.4.3. |
Vilken är den längsta båge du kan bearbeta? |
Vi använder storcirkelbågar som "interpoleringslinje" mellan två punkter. Det innebär att två punkter faktiskt sammanfogas på två olika sätt, beroende på vilken riktning du färdas längs storcirkeln. All vår kod förutsätter att punkterna sammanfogas av den *kortaste* av de två vägarna längs storcirkeln. Som en följd av detta kommer former som har bågar på mer än 180 grader inte att modelleras korrekt. |
|
4.3.4.4. |
Varför är det så långsamt att beräkna området Europa / Ryssland / infoga stor geografisk region här ? |
Eftersom polygonen är så jäkla stor! Stora områden är dåliga av två skäl: deras gränser är enorma, så indexet tenderar att dra funktionen oavsett vilken fråga du kör; antalet toppar är enormt, och tester (avstånd, inneslutning) måste korsa topplistan minst en gång och ibland N gånger (med N som antalet toppar i den andra kandidatfunktionen). Precis som med GEOMETRY rekommenderar vi att du, när du har mycket stora polygoner men gör sökningar i små områden, "denormaliserar" dina geometriska data i mindre bitar så att indexet effektivt kan göra underfrågor på delar av objektet och så att sökningarna inte behöver ta fram hela objektet varje gång. Vänligen se ST_Subdivide funktionsdokumentation. Bara för att du *kan* lagra hela Europa i en polygon betyder det inte att du *bör* göra det. |
PostGIS är förenligt med Open Geospatial Consortiums (OGC) specifikation för enkla funktioner. Denna standard definierar begreppen enkel och giltig geometri. Dessa definitioner gör det möjligt för geometrimodellen Simple Features att representera spatiala objekt på ett konsekvent och otvetydigt sätt som stöder effektiva beräkningar. (Obs: OGC SF och SQL/MM har samma definitioner för enkel och giltig)
En enkel geometri är en geometri som inte har några avvikande geometriska punkter, t.ex. självskärning eller självtangentiering.
En POINT
är i sig själv enkel som ett 0-dimensionellt geometriobjekt.
MULTIPOINTs
är enkla om inte två koordinater(POINTs)
är lika (har identiska koordinatvärden).
En LINESTRING
är enkel om den inte passerar genom samma punkt två gånger, med undantag för ändpunkterna. Om ändpunkterna på en enkel LineString är identiska kallas den sluten och kallas för en Linear Ring.
(a) och (c) är enkla |
![]() (a) |
![]() (b) |
![]() (c) |
![]() (d) |
En MULTILINESTRING
är enkel endast om alla dess element är enkla och den enda skärningen mellan två element sker i punkter som ligger på båda elementens gränser.
(e) och (f) är enkla |
![]() (e) |
![]() (f) |
![]() (g) |
POLYGONER
bildas av linjära ringar, så giltig polygonal geometri är alltid enkel.
För att testa om en geometri är enkel kan du använda funktionen ST_IsSimple:
SELECT ST_IsSimple('LINESTRING(0 0, 100 100)') AS straight, ST_IsSimple('LINESTRING(0 0, 100 100, 100 0, 0 100)') AS crossing; straight | crossing ----------+---------- t | f
Generellt kräver inte PostGIS-funktioner att geometriska argument ska vara enkla. Enkelhet används främst som en grund för att definiera geometrisk validitet. Det är också ett krav för vissa typer av spatiala datamodeller (t.ex. tillåter linjära nätverk ofta inte linjer som korsar varandra). Multipunkts- och linjärgeometri kan göras enkel med hjälp av ST_UnaryUnion.
Geometrisk validitet gäller främst för 2-dimensionella geometrier(POLYGONER
och MULTIPOLYGONER
). Validiteten definieras av regler som gör att polygonal geometri kan modellera plana områden på ett otvetydigt sätt.
En POLYGON
är giltig om:
polygonens begränsningsringar (den yttre skalringen och de inre hålringarna) är enkla (korsar inte varandra och berör inte varandra). På grund av detta kan en polygon inte ha snittlinjer, spikar eller öglor. Detta innebär att polygonhål måste representeras som inre ringar, snarare än genom att den yttre ringen självberör (ett s.k. "inverterat hål").
gränsringarna korsar inte varandra
begränsningsringar kan beröra varandra i punkter men endast som en tangent (dvs. inte i en linje)
inre ringar är inneslutna i den yttre ringen
polygonens inre är enkelt sammanhängande (dvs. ringarna får inte beröra varandra på ett sätt som delar upp polygonen i mer än en del)
(h) och (i) är giltiga |
![]() (h) |
![]() (i) |
![]() (j) |
![]() (k) |
![]() (l) |
![]() (m) |
En MULTIPOLYGON
är giltig om:
dess element POLYGONER
är giltiga
elementen inte överlappar varandra (dvs. deras insidor får inte skära varandra)
elementen berör varandra endast i punkter (dvs. inte längs en linje)
(n) är en giltig |
![]() (n) |
![]() (o) |
![]() (p) |
Dessa regler innebär att giltig polygonal geometri också är enkel..
För linjär geometri är den enda giltighetsregeln att LINESTRINGs
måste ha minst två punkter och ha en längd som inte är noll (eller motsvarande, ha minst två distinkta punkter.) Observera att icke-enkla (självskärande) linjer är giltiga.
SELECT ST_IsValid('LINESTRING(0 0, 1 1)') AS len_nonzero, ST_IsValid('LINESTRING(0 0, 0 0, 0 0)') AS len_zero, ST_IsValid('LINESTRING(10 10, 150 150, 180 50, 20 130)') AS self_int; len_nonzero | len_zero | self_int -------------+----------+---------- t | f | t
POINT-
och MULTIPOINT-geometrierna
har inga giltighetsregler.
PostGIS tillåter skapande och lagring av både giltig och ogiltig geometri. Detta gör att ogiltig geometri kan upptäckas och flaggas eller fixas. Det finns också situationer där OGC:s giltighetsregler är strängare än önskat (exempel på detta är linestrings med noll längd och polygoner med inverterade hål)
Många av de funktioner som PostGIS tillhandahåller förutsätter att geometriargumenten är giltiga. Det är till exempel inte meningsfullt att beräkna arean av en polygon som har ett hål definierat utanför polygonen, eller att konstruera en polygon från en icke-enkel begränsningslinje. Genom att anta giltiga geometriska indata kan funktioner arbeta mer effektivt, eftersom de inte behöver kontrollera att de är topologiskt korrekta. (Noterbara undantag är att nollängdslinjer och polygoner med inversioner i allmänhet hanteras korrekt) Dessutom producerar de flesta PostGIS-funktioner giltiga geometriska utdata om indata är giltiga. Detta gör att PostGIS-funktioner kan kedjas ihop på ett säkert sätt.
Om du stöter på oväntade felmeddelanden när du anropar PostGIS-funktioner (t.ex. "GEOS Intersection() kastade ett fel!") bör du först bekräfta att funktionsargumenten är giltiga. Om de inte är det bör du överväga att använda någon av nedanstående tekniker för att säkerställa att de data du bearbetar är giltiga.
![]() |
|
Om en funktion rapporterar ett fel med giltiga indata kan du ha hittat ett fel i antingen PostGIS eller ett av de bibliotek som används, och du bör rapportera detta till PostGIS-projektet. Detsamma gäller om en PostGIS-funktion returnerar en ogiltig geometri för giltig indata. |
För att testa om en geometri är giltig kan du använda funktionen ST_IsValid:
SELECT ST_IsValid('POLYGON ((20 180, 180 180, 180 20, 20 20, 20 180))'); ----------------- t
Information om arten av och platsen för en geometrisk invaliditet tillhandahålls av funktionen ST_IsValidDetail:
SELECT valid, reason, ST_AsText(location) AS location FROM ST_IsValidDetail('POLYGON ((20 20, 120 190, 50 190, 170 50, 20 20))') AS t; valid | reason | location -------+-------------------+--------------------------------------------- f | Self-intersection | POINT(91.51162790697674 141.56976744186045)
I vissa situationer är det önskvärt att korrigera ogiltig geometri automatiskt. Använd funktionen ST_MakeValid för att göra detta.(ST_MakeValid
är ett exempel på en spatial funktion som tillåter ogiltiga indata!)
Som standard kontrollerar PostGIS inte giltigheten vid laddning av geometri, eftersom giltighetstestning kan ta mycket CPU-tid för komplexa geometrier. Om du inte litar på dina datakällor kan du tvinga fram en giltighetskontroll på dina tabeller genom att lägga till en check constraint:
ALTER TABLE mytable ADD CONSTRAINT geometry_valid_check CHECK (ST_IsValid(geom));
Ett spatialt referenssystem (SRS) (även kallat koordinatreferenssystem (CRS)) definierar hur geometri refereras till platser på jordens yta. Det finns tre typer av SRS:
En geodetisk SRS använder vinkelkoordinater (longitud och latitud) som kartläggs direkt på jordytan.
En projicerad SRS använder en matematisk projektionstransformation för att "platta till" ytan på den sfäroida jorden till ett plan. Den tilldelar platskoordinater på ett sätt som gör det möjligt att direkt mäta storheter som avstånd, yta och vinkel. Koordinatsystemet är kartesiskt, vilket innebär att det har en definierad ursprungspunkt och två vinkelräta axlar (vanligtvis orienterade mot norr och öster). Varje projicerad SRS använder en angiven längdenhet (vanligtvis meter eller fot). En projicerad SRS kan vara begränsad i sitt tillämpningsområde för att undvika distorsion och passa inom de definierade koordinatgränserna.
Ett lokalt SRS är ett kartesiskt koordinatsystem som inte är refererat till jordytan. I PostGIS specificeras detta med ett SRID-värde på 0.
Det finns många olika spatiala referenssystem i bruk. Vanliga SRS är standardiserade i European Petroleum Survey Group EPSG-databasen. För enkelhetens skull hänvisar PostGIS (och många andra spatiala system) till SRS-definitioner med hjälp av en heltalsidentifierare som kallas SRID.
En geometri är associerad med ett spatialt referenssystem genom sitt SRID-värde, som nås via ST_SRID. SRID för en geometri kan tilldelas med hjälp av ST_SetSRID. Vissa geometry constructor-funktioner gör det möjligt att ange en SRID (t.ex. ST_Point och ST_MakeEnvelope). EWKT-formatet stöder SRID med prefixet SRID=n;.
.
Spatiala funktioner som bearbetar par av geometrier (t.ex. överlagrings- och relationsfunktioner ) kräver att de ingående geometrierna finns i samma spatiala referenssystem (har samma SRID). Geometridata kan omvandlas till ett annat spatialt referenssystem med hjälp av ST_Transform och ST_TransformPipeline. Geometri som returneras från funktioner har samma SRS som indatageometrierna.
Tabellen SPATIAL_REF_SYS
som används av PostGIS är en OGC-kompatibel databastabell som definierar de tillgängliga spatiala referenssystemen. Den innehåller de numeriska SRID:erna och textbeskrivningarna av koordinatsystemen.
Definitionen av tabellen spatial_ref_sys
är:
CREATE TABLE spatial_ref_sys ( srid INTEGER NOT NULL PRIMARY KEY, auth_name VARCHAR(256), auth_srid INTEGER, srtext VARCHAR(2048), proj4text VARCHAR(2048) )
Kolumnerna är..:
srid
En heltalskod som unikt identifierar det spatiala referenssystemet (SRS) i databasen.
auth_name
Namnet på den standard eller det standardiseringsorgan som åberopas för detta referenssystem. Exempelvis är "EPSG" ett giltigt auth_name
.
auth_srid
ID för det spatiala referenssystemet enligt definitionen av den myndighet som anges i auth_name
. När det gäller EPSG är detta EPSG-koden.
srtext
Representationen av det spatiala referenssystemet i Well-Known Text. Ett exempel på en WKT SRS-representation är:
PROJCS["NAD83 / UTM Zone 10N", GEOGCS["NAD83", DATUM["North_American_Datum_1983", SPHEROID["GRS 1980",6378137,298.257222101] ], PRIMEM["Greenwich",0], UNIT["degree",0.0174532925199433] ], PROJECTION["Transverse_Mercator"], PARAMETER["latitude_of_origin",0], PARAMETER["central_meridian",-123], PARAMETER["scale_factor",0.9996], PARAMETER["false_easting",500000], PARAMETER["false_northing",0], UNIT["metre",1] ]
För en diskussion om SRS WKT, se OGC-standarden Well-known text representation of coordinate reference systems.
proj4text
PostGIS använder PROJ-biblioteket för att tillhandahålla funktioner för koordinattransformation. Kolumnen proj4text
innehåller PROJ-koordinatdefinitionssträngen för en viss SRID. Till exempel:
+proj=utm +zone=10 +ellps=clrk66 +datum=NAD27 +units=m
Mer information finns på PROJ-webbplatsen. Filen spatial_ref_sys.sql
innehåller både srtext-
och proj4text-definitioner
för alla EPSG-projektioner.
Vid hämtning av definitioner av spatiala referenssystem för användning i transformationer använder PostGIS följande strategi:
Om auth_name
och auth_srid
finns (icke-NULL) används PROJ SRS baserat på dessa poster (om en sådan finns).
Om srtext
finns kan du om möjligt skapa en SRS med hjälp av den.
Om proj4text
finns kan du om möjligt skapa en SRS med hjälp av den.
Tabellen PostGIS spatial_ref_sys
innehåller över 3000 av de vanligaste definitionerna av spatiala referenssystem som hanteras av PROJ-projektionsbiblioteket. Men det finns många koordinatsystem som den inte innehåller. Du kan lägga till SRS-definitioner i tabellen om du har den information som krävs om det spatiala referenssystemet. Eller så kan du definiera ditt eget spatiala referenssystem om du är bekant med PROJ constructs. Tänk på att de flesta spatiala referenssystem är regionala och inte har någon betydelse när de används utanför de gränser som de är avsedda för.
En resurs för att hitta spatiala referenssystem som inte definieras i kärnuppsättningen är http://spatialreference.org/
Några vanligt förekommande spatiala referenssystem är: 4326 - WGS 84 Long Lat, 4269 - NAD 83 Long Lat, 3395 - WGS 84 World Mercator, 2163 - US National Atlas Equal Area och de 60 WGS84 UTM-zonerna. UTM-zoner är en av de mest idealiska för mätning, men täcker endast 6-gradersregioner. (För att avgöra vilken UTM-zon som ska användas för ditt intresseområde, se hjälpfunktionen utmzone PostGIS plpgsql)
Amerikanska delstater använder spatiala referenssystem i State Plane (meter- eller fotbaserade) - vanligtvis finns ett eller två per delstat. De flesta av de meterbaserade finns i kärnuppsättningen, men många av de fotbaserade eller ESRI-skapade måste kopieras från spatialreference.org.
Du kan även definiera koordinatsystem som inte är jordbaserade, t.ex. Mars 2000 Mars koordinatsystem är inte planar (det är i grader sfäroidalt), men du kan använda det med geograftypen
för att få längd- och avståndsmätningar i meter i stället för grader.
Här är ett exempel på laddning av ett anpassat koordinatsystem med hjälp av en icke tilldelad SRID och PROJ-definitionen för en US-centrisk Lambert Conformal-projektion:
INSERT INTO spatial_ref_sys (srid, proj4text) VALUES ( 990000, '+proj=lcc +lon_0=-95 +lat_0=25 +lat_1=25 +lat_2=25 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs' );
Du kan skapa en tabell för att lagra geometridata genom att använda SQL-satsen CREATE TABLE med en kolumn av typen geometry
. I följande exempel skapas en tabell med en geometrikolumn som lagrar 2D (XY) LineStrings i BC-Albers koordinatsystem (SRID 3005):
CREATE TABLE roads ( id SERIAL PRIMARY KEY, name VARCHAR(64), geom geometry(LINESTRING,3005) );
Geometritypen
har stöd för två valfria typmodifierare:
Modifieraren för spatial typ begränsar vilken typ av former och dimensioner som tillåts i kolumnen. Värdet kan vara vilken som helst av de undertyper av geometri som stöds (t.ex. POINT, LINESTRING, POLYGON, MULTIPOINT, MULTILINESTRING, MULTIPOLYGON, GEOMETRYCOLLECTION etc.). Modifieraren stöder begränsningar av koordinatdimensionalitet genom att lägga till suffix: Z, M och ZM. En modifierare av typen "LINESTRINGM" tillåter t.ex. endast linestrings med tre dimensioner och behandlar den tredje dimensionen som ett mått. På samma sätt kräver "POINTZM" fyrdimensionella (XYZM) data.
sRID-modifieraren begränsar det spatiala referenssystemets SRID till ett visst nummer. Om den utelämnas är SRID standardvärdet 0.
Exempel på hur man skapar tabeller med geometrikolumner:
Skapa en tabell som innehåller alla typer av geometrier med standard-SRID:
CREATE TABLE geoms(gid serial PRIMARY KEY, geom geometry );
Skapa en tabell med 2D POINT-geometri med standard-SRID:
CREATE TABLE pts(gid serial PRIMARY KEY, geom geometry(POINT) );
Skapa en tabell med 3D (XYZ) POINTs och en explicit SRID på 3005:
CREATE TABLE pts(gid serial PRIMARY KEY, geom geometry(POINTZ,3005) );
Skapa en tabell med 4D (XYZM) LINESTRING-geometri med standard SRID:
CREATE TABLE lines(gid serial PRIMARY KEY, geom geometry(LINESTRINGZM) );
Skapa en tabell med 2D POLYGON-geometri med SRID 4267 (NAD 1927 long lat):
CREATE TABLE polys(gid serial PRIMARY KEY, geom geometry(POLYGON,4267) );
Det är möjligt att ha mer än en geometrikolumn i en tabell. Detta kan anges när tabellen skapas, eller så kan en kolumn läggas till med SQL-satsen ALTER TABLE. I detta exempel läggs en kolumn till som kan innehålla 3D LineStrings:
ALTER TABLE roads ADD COLUMN geom2 geometry(LINESTRINGZ,4326);
OGC:s Simple Features Specification for SQL definierar metadatatabellen GEOMETRY_COLUMNS
för att beskriva geometritabellens struktur. I PostGIS är geometry_columns
en vy som läser från databassystemets katalogtabeller. Detta säkerställer att den spatiala metadatainformationen alltid överensstämmer med de tabeller och vyer som för närvarande definieras. Vyn har följande struktur:
\d geometry_columns
View "public.geometry_columns" Column | Type | Modifiers -------------------+------------------------+----------- f_table_catalog | character varying(256) | f_table_schema | character varying(256) | f_table_name | character varying(256) | f_geometry_column | character varying(256) | coord_dimension | integer | srid | integer | type | character varying(30) |
Kolumnerna är..:
f_table_catalog, f_table_schema, f_table_name
Det fullständigt kvalificerade namnet på funktionstabellen som innehåller geometrikolumnen. Det finns ingen PostgreSQL-analog av "katalog" så den kolumnen lämnas tom. För "schema" används PostgreSQL-schemanamnet(offentligt
är standard).
f_geometry_column
Namnet på geometrikolumnen i feature-tabellen.
coord_dimension
Koordinatdimensionen (2, 3 eller 4) för kolumnen.
srid
ID för det spatiala referenssystem som används för koordinatgeometrin i denna tabell. Det är en främmande nyckelreferens till tabellen spatial_ref_sys
(se Section 4.5.1, “Tabellen SPATIAL_REF_SYS”).
type
Typen av det spatiala objektet. För att begränsa den spatiala kolumnen till en enda typ, använd en av följande: POINT, LINESTRING, POLYGON, MULTIPOINT, MULTILINESTRING, MULTIPOLYGON, GEOMETRYCOLLECTION eller motsvarande XYM-versioner POINTM, LINESTRINGM, POLYGONM, MULTIPOINTM, MULTILINESTRINGM, MULTIPOLYGONM, GEOMETRYCOLLECTIONM. För heterogena samlingar (av blandad typ) kan du använda "GEOMETRY" som typ.
Två av de fall där du kan behöva detta är vid SQL Views och bulkinsättningar. För bulkinsättningar kan du korrigera registreringen i geometry_columns-tabellen genom att begränsa kolumnen eller göra en alter table. För vyer kan du exponera med hjälp av en CAST-operation. Observera att om din kolumn är typmodbaserad kommer skapandeprocessen att registrera den korrekt, så du behöver inte göra någonting. Även vyer som inte har någon spatial funktion applicerad på geometrin kommer att registreras på samma sätt som den underliggande tabellgeometrikolumnen.
-- Lets say you have a view created like this CREATE VIEW public.vwmytablemercator AS SELECT gid, ST_Transform(geom, 3395) As geom, f_name FROM public.mytable; -- For it to register correctly -- You need to cast the geometry -- DROP VIEW public.vwmytablemercator; CREATE VIEW public.vwmytablemercator AS SELECT gid, ST_Transform(geom, 3395)::geometry(Geometry, 3395) As geom, f_name FROM public.mytable; -- If you know the geometry type for sure is a 2D POLYGON then you could do DROP VIEW public.vwmytablemercator; CREATE VIEW public.vwmytablemercator AS SELECT gid, ST_Transform(geom,3395)::geometry(Polygon, 3395) As geom, f_name FROM public.mytable;
--Lets say you created a derivative table by doing a bulk insert SELECT poi.gid, poi.geom, citybounds.city_name INTO myschema.my_special_pois FROM poi INNER JOIN citybounds ON ST_Intersects(citybounds.geom, poi.geom); -- Create 2D index on new table CREATE INDEX idx_myschema_myspecialpois_geom_gist ON myschema.my_special_pois USING gist(geom); -- If your points are 3D points or 3M points, -- then you might want to create an nd index instead of a 2D index CREATE INDEX my_special_pois_geom_gist_nd ON my_special_pois USING gist(geom gist_geometry_ops_nd); -- To manually register this new table's geometry column in geometry_columns. -- Note it will also change the underlying structure of the table to -- to make the column typmod based. SELECT populate_geometry_columns('myschema.my_special_pois'::regclass); -- If you are using PostGIS 2.0 and for whatever reason, you -- you need the constraint based definition behavior -- (such as case of inherited tables where all children do not have the same type and srid) -- set optional use_typmod argument to false SELECT populate_geometry_columns('myschema.my_special_pois'::regclass, false);
Även om den gamla metoden med begränsningar fortfarande stöds, kommer en geometrikolumn som baseras på begränsningar och som används direkt i en vy inte att registreras korrekt i geometry_columns, vilket en typmod-kolumn gör. I det här exemplet definierar vi en kolumn med hjälp av typmod och en annan med hjälp av constraints.
CREATE TABLE pois_ny(gid SERIAL PRIMARY KEY, poi_name text, cat text, geom geometry(POINT,4326)); SELECT AddGeometryColumn('pois_ny', 'geom_2160', 2160, 'POINT', 2, false);
Om vi kör i psql
\d pois_ny;
Vi ser att de definieras på olika sätt - en är typmod, en är begränsning
Table "public.pois_ny" Column | Type | Modifiers -----------+-----------------------+------------------------------------------------------ gid | integer | not null default nextval('pois_ny_gid_seq'::regclass) poi_name | text | cat | character varying(20) | geom | geometry(Point,4326) | geom_2160 | geometry | Indexes: "pois_ny_pkey" PRIMARY KEY, btree (gid) Check constraints: "enforce_dims_geom_2160" CHECK (st_ndims(geom_2160) = 2) "enforce_geotype_geom_2160" CHECK (geometrytype(geom_2160) = 'POINT'::text OR geom_2160 IS NULL) "enforce_srid_geom_2160" CHECK (st_srid(geom_2160) = 2160)
I geometry_columns registreras de båda korrekt
SELECT f_table_name, f_geometry_column, srid, type FROM geometry_columns WHERE f_table_name = 'pois_ny';
f_table_name | f_geometry_column | srid | type -------------+-------------------+------+------- pois_ny | geom | 4326 | POINT pois_ny | geom_2160 | 2160 | POINT
Men - om vi skulle skapa en vy så här
CREATE VIEW vw_pois_ny_parks AS SELECT * FROM pois_ny WHERE cat='park'; SELECT f_table_name, f_geometry_column, srid, type FROM geometry_columns WHERE f_table_name = 'vw_pois_ny_parks';
Den typmodbaserade geom view-kolumnen registreras korrekt, men den constraintbaserade gör det inte.
f_table_name | f_geometry_column | srid | type ------------------+-------------------+------+---------- vw_pois_ny_parks | geom | 4326 | POINT vw_pois_ny_parks | geom_2160 | 0 | GEOMETRY
Detta kan komma att ändras i framtida versioner av PostGIS, men för närvarande måste du göra så här för att tvinga den begränsningsbaserade vykolumnen att registreras korrekt:
DROP VIEW vw_pois_ny_parks; CREATE VIEW vw_pois_ny_parks AS SELECT gid, poi_name, cat, geom, geom_2160::geometry(POINT,2160) As geom_2160 FROM pois_ny WHERE cat = 'park'; SELECT f_table_name, f_geometry_column, srid, type FROM geometry_columns WHERE f_table_name = 'vw_pois_ny_parks';
f_table_name | f_geometry_column | srid | type ------------------+-------------------+------+------- vw_pois_ny_parks | geom | 4326 | POINT vw_pois_ny_parks | geom_2160 | 2160 | POINT
När du har skapat en spatial tabell är du redo att ladda upp spatiala data till databasen. Det finns två inbyggda sätt att få spatiala data till en PostGIS/PostgreSQL-databas: med hjälp av formaterade SQL-satser eller med hjälp av Shapefile-laddaren.
Om spatiala data kan konverteras till en textrepresentation (som antingen WKT eller WKB) kan SQL vara det enklaste sättet att få in data i PostGIS. Data kan bulk-laddas in i PostGIS/PostgreSQL genom att ladda en textfil med SQL INSERT-satser
med hjälp av SQL-verktyget psql
.
En SQL-laddningsfil (till exempelroads.sql)
kan se ut så här:
BEGIN; INSERT INTO roads (road_id, roads_geom, road_name) VALUES (1,'LINESTRING(191232 243118,191108 243242)','Jeff Rd'); INSERT INTO roads (road_id, roads_geom, road_name) VALUES (2,'LINESTRING(189141 244158,189265 244817)','Geordie Rd'); INSERT INTO roads (road_id, roads_geom, road_name) VALUES (3,'LINESTRING(192783 228138,192612 229814)','Paul St'); INSERT INTO roads (road_id, roads_geom, road_name) VALUES (4,'LINESTRING(189412 252431,189631 259122)','Graeme Ave'); INSERT INTO roads (road_id, roads_geom, road_name) VALUES (5,'LINESTRING(190131 224148,190871 228134)','Phil Tce'); INSERT INTO roads (road_id, roads_geom, road_name) VALUES (6,'LINESTRING(198231 263418,198213 268322)','Dave Cres'); COMMIT;
SQL-filen kan laddas in i PostgreSQL med psql
:
psql -d [database] -f roads.sql
Shp2pgsql-dataladdaren
konverterar Shapefiles till SQL som är lämplig för införande i en PostGIS / PostgreSQL-databas antingen i geometri- eller geografiformat. Laddaren har flera driftlägen som väljs med kommandoradsflaggor.
Det finns också ett grafiskt gränssnitt shp2pgsql-gui
med de flesta av alternativen som kommandoradsladdaren. Detta kan vara lättare att använda för engångsladdning utan skript eller om du är nybörjare på PostGIS. Det kan också konfigureras som ett plugin till PgAdminIII.
-c
Skapar en ny tabell och fyller i den från Shapefilen. Detta är standardläget.
-a
Lägger till data från Shapefilen i databastabellen. Observera att filerna måste ha samma attribut och samma datatyper om du vill använda det här alternativet för att läsa in flera filer.
-d
Slänger databastabellen innan en ny tabell skapas med data från Shapefilen.
-p
Producerar endast SQL-koden för tabellskapande, utan att lägga till några faktiska data. Detta kan användas om du helt vill separera stegen för att skapa tabeller och läsa in data.
-?
Visa hjälpskärm.
-D
Använd PostgreSQL "dump" -formatet för utdata. Detta kan kombineras med -a, -c och -d. Det är mycket snabbare att läsa in än standard SQL-formatet "insert". Använd detta för mycket stora datamängder.
-s [<FROM_SRID>:]<SRID>
Skapar och fyller på geometritabellerna med den angivna SRID:en. Anger eventuellt att den ingående shapefilen använder den angivna FROM_SRID, i vilket fall geometrierna kommer att omprojiceras till mål-SRID.
-k
Behåll identifierarnas versaler (kolumn, schema och attribut). Observera att alla attribut i Shapefile är UPPPPERCASE.
-i
Tvinga alla heltal till standard 32-bitars heltal, skapa inte 64-bitars bigints, även om DBF-headerns signatur verkar motivera det.
-I
Skapa ett GiST-index på geometrikolumnen.
-m
-m a_file_name
Ange en fil som innehåller en uppsättning mappningar av (långa) kolumnnamn till DBF-kolumnnamn med 10 tecken. Filens innehåll är en eller flera rader med två namn åtskilda av blanksteg utan efterföljande eller inledande blanksteg. Exempel på detta:
COLUMNNAME DBFFIELD1 AVERYLONGCOLUMNNAME DBFFIELD2
-S
Generera enkla geometrier i stället för MULTI-geometrier. Kommer endast att lyckas om alla geometrier faktiskt är enkla (t.ex. en MULTIPOLYGON med ett enda skal eller en MULTIPOINT med ett enda vertex).
-t <dimensionality>
Tvingar utdatageometrin att ha den angivna dimensionaliteten. Använd följande strängar för att ange dimensionaliteten: 2D, 3DZ, 3DM, 4D.
Om indata har färre dimensioner än vad som anges, kommer dessa dimensioner att fyllas i med nollor i utdata. Om indata har fler dimensioner än vad som anges, kommer de oönskade dimensionerna att tas bort.
-w
Utdata i WKT-format istället för WKB. Observera att detta kan medföra koordinatavvikelser på grund av förlorad precision.
-e
Exekvera varje sats för sig, utan att använda en transaktion. Detta gör det möjligt att läsa in majoriteten av bra data när det finns några dåliga geometrier som genererar fel. Observera att detta inte kan användas med flaggan -D eftersom "dump"-formatet alltid använder en transaktion.
-W <encoding>
Ange kodning av indata (dbf-fil). När detta används konverteras alla attribut i dbf-filen från den angivna kodningen till UTF8. Den resulterande SQL-utdata kommer att innehålla ett SET CLIENT_ENCODING till UTF8-kommando
, så att backend kan konvertera om från UTF8 till den kodning som databasen är konfigurerad att använda internt.
-N <policy>
Policy för hantering av NULL-geometrier (insert*,skip,abort)
-n
-n Importera endast DBF-fil. Om dina data inte har någon motsvarande shapefil kommer den automatiskt att växla till detta läge och bara läsa in dbf-filen. Så att ställa in denna flagga behövs bara om du har en fullständig shapefiluppsättning och du bara vill ha attributdata och ingen geometri.
-G
Använd geografin i stället för geometrin (kräver lon/lat-data) i WGS84 long lat (SRID=4326)
-T <tablespace>
Ange tablespace för den nya tabellen. Index kommer fortfarande att använda standardbordsytan om inte -X-parametern också används. PostgreSQL-dokumentationen har en bra beskrivning av när man ska använda anpassade tablespaces.
-X <tablespace>
Ange tablespace för den nya tabellens index. Detta gäller för primärnyckelindexet och det spatiala GIST-indexet om -I också används.
-Z
När denna flagga används förhindrar den att ANALYZE-satser
genereras. Utan flaggan -Z (standardbeteende) kommer ANALYZE-satserna
att genereras.
Ett exempel på en session där laddaren används för att skapa en inmatningsfil och ladda den kan se ut så här:
# shp2pgsql -c -D -s 4269 -i -I shaperoads.shp myschema.roadstable > roads.sql # psql -d roadsdb -f roads.sql
En konvertering och laddning kan göras i ett steg med hjälp av UNIX pipes:
# shp2pgsql shaperoads.shp myschema.roadstable | psql -d roadsdb
Spatiala data kan extraheras från databasen med hjälp av antingen SQL eller Shapefile-dumpern. I avsnittet om SQL presenteras några av de funktioner som finns tillgängliga för att göra jämförelser och frågor om spatiala tabeller.
Det enklaste sättet att extrahera spatiala data ur databasen är att använda en SQL SELECT-fråga
för att definiera den datauppsättning som ska extraheras och dumpa de resulterande kolumnerna i en textfil som kan analyseras:
db=# SELECT road_id, ST_AsText(road_geom) AS geom, road_name FROM roads; road_id | geom | road_name --------+-----------------------------------------+----------- 1 | LINESTRING(191232 243118,191108 243242) | Jeff Rd 2 | LINESTRING(189141 244158,189265 244817) | Geordie Rd 3 | LINESTRING(192783 228138,192612 229814) | Paul St 4 | LINESTRING(189412 252431,189631 259122) | Graeme Ave 5 | LINESTRING(190131 224148,190871 228134) | Phil Tce 6 | LINESTRING(198231 263418,198213 268322) | Dave Cres 7 | LINESTRING(218421 284121,224123 241231) | Chris Way (6 rows)
Det kommer att finnas tillfällen då någon form av begränsning är nödvändig för att minska antalet poster som returneras. När det gäller attributbaserade begränsningar använder du samma SQL-syntax som för en icke spatial tabell. När det gäller spatiala begränsningar är följande funktioner användbara:
ST_Intersects
Denna funktion visar om två geometrier delar på något utrymme.
=
Detta testar om två geometrier är geometriskt identiska. Till exempel om "POLYGON((0 0,1 1,1 0,0 0))" är samma sak som "POLYGON((0 0,1 1,1 0,0 0))" (det är det).
Därefter kan du använda dessa operatorer i frågor. Observera att när du anger geometrier och boxar på SQL-kommandoraden måste du uttryckligen omvandla strängrepresentationerna till geometrier-funktionen. 312 är ett fiktivt spatialt referenssystem som matchar våra data. Så till exempel:
SELECT road_id, road_name FROM roads WHERE roads_geom='SRID=312;LINESTRING(191232 243118,191108 243242)'::geometry;
Ovanstående fråga skulle returnera den enda post från tabellen "ROADS_GEOM" där geometrin var lika med det värdet.
För att kontrollera om någon av vägarna passerar inom det område som definieras av en polygon:
SELECT road_id, road_name FROM roads WHERE ST_Intersects(roads_geom, 'SRID=312;POLYGON((...))');
Den vanligaste spatiala frågan kommer förmodligen att vara en "rambaserad" fråga som används av klientprogramvara, t.ex. webbläsare och webbmappare, för att hämta en "kartram" med data för visning.
När du använder operatorn "&&" kan du ange antingen en BOX3D som jämförelsefunktion eller en GEOMETRY. När du anger en GEOMETRY kommer dock dess bounding box att användas för jämförelsen.
Om du använder ett "BOX3D"-objekt som ram ser en sådan fråga ut så här:
SELECT ST_AsText(roads_geom) AS geom FROM roads WHERE roads_geom && ST_MakeEnvelope(191232, 243117,191232, 243119,312);
Notera användningen av SRID 312 för att specificera kuvertets projektion.
Tabelldumpern pgsql2shp
ansluter till databasen och konverterar en tabell (eventuellt definierad av en fråga) till en shape-fil. Den grundläggande syntaxen är:
pgsql2shp [<options >] <database > [<schema >.]<table>
pgsql2shp [<options >] <database > <query>
Alternativen för kommandoraden är:
-f <filename>
Skriv utdata till ett visst filnamn.
-h <host>
Databasens värd att ansluta till.
-p <port>
Porten att ansluta till på databasens värd.
-P <password>
Det lösenord som ska användas vid anslutning till databasen.
-u <user>
Det användarnamn som ska användas vid anslutning till databasen.
-g <geometry column>
I tabeller med flera geometrikolumner, den geometrikolumn som ska användas när shape-filen skrivs.
-b
Använd en binär markör. Detta gör operationen snabbare, men fungerar inte om något attribut i tabellen som inte är geometriskt saknar en cast till text.
-r
Rått läge. Släpp inte fältet gid
eller escape kolumnnamn.
-m filename
Omvandla identifierare till namn med tio tecken. Filens innehåll består av rader med två symboler åtskilda av ett enda vitt mellanslag utan vare sig efterföljande eller inledande mellanslag: VERYLONGSYMBOL SHORTONE ANOTHERVERYLONGSYMBOL SHORTER etc.
Spatiala index gör det möjligt att använda en spatial databas för stora datamängder. Utan indexering kräver en sökning efter funktioner en sekventiell genomsökning av varje post i databasen. Indexering snabbar upp sökningen genom att organisera data i en struktur som snabbt kan genomgås för att hitta matchande poster.
Den indexmetod med B-träd som vanligen används för attributdata är inte särskilt användbar för spatiala data, eftersom den endast stöder lagring och sökning av data i en enda dimension. Data som geometri (som har två eller flera dimensioner) kräver en indexmetod som stöder intervallfråga över alla datadimensioner. En av de viktigaste fördelarna med PostgreSQL för spatial datahantering är att den erbjuder flera typer av indexmetoder som fungerar bra för flerdimensionella data: GiST-, BRIN- och SP-GiST-index.
GiST-index (Generalized Search Tree) delar upp data i "saker på ena sidan", "saker som överlappar", "saker som är inuti" och kan användas på ett brett spektrum av datatyper, inklusive GIS-data. PostGIS använder ett R-Tree-index som implementerats ovanpå GiST för att indexera spatiala data. GiST är den vanligaste och mest mångsidiga metoden för spatiala index och erbjuder mycket bra prestanda vid sökningar.
BRIN-index (Block Range Index) fungerar genom att sammanfatta den spatiala omfattningen av intervall av tabellposter. Sökningen görs via en skanning av intervallen. BRIN är endast lämpligt att använda för vissa typer av data (spatialt sorterade, med sällsynta eller inga uppdateringar). Men det ger mycket snabbare tid för att skapa index och mycket mindre indexstorlek.
SP-GiST (Space-Partitioned Generalized Search Tree) är en generisk indexmetod som stöder partitionerade sökträd som quad-trees, k-d-träd och radix-träd (tries).
Spatiala index lagrar endast geometriernas avgränsande box. Spatiala frågor använder indexet som ett primärt filter för att snabbt fastställa en uppsättning geometrier som potentiellt matchar frågevillkoret. De flesta spatiala frågor kräver ett sekundärt filter som använder en spatial predikatfunktion för att testa ett mer specifikt spatialt villkor. Mer information om hur du ställer frågor med spatiala predikat finns på Section 5.2, “Använda spatiala index”.
Se även PostGIS Workshop-avsnittet om spatiala index och PostgreSQL-handboken.
GiST står för "Generalized Search Tree" och är en generisk form av indexering för flerdimensionella data. PostGIS använder ett R-Tree-index som implementerats ovanpå GiST för att indexera spatiala data. GiST är den vanligaste och mest mångsidiga metoden för spatial indexering och erbjuder mycket bra sökprestanda. Andra implementeringar av GiST används för att påskynda sökningar på alla typer av oregelbundna datastrukturer (heltalsarrayer, spektraldata etc.) som inte är mottagliga för normal B-Tree-indexering. För mer information se PostgreSQL-manualen.
När en spatial datatabell överstiger några tusen rader vill du bygga ett index för att påskynda spatiala sökningar av data (såvida inte alla dina sökningar baseras på attribut, i vilket fall du vill bygga ett normalt index på attributfälten).
Syntaxen för att bygga ett GiST-index på en "geometri"-kolumn är följande:
CREATE INDEX [indexname] ON [tablename] USING GIST ( [geometryfield] );
Syntaxen ovan skapar alltid ett 2D-index. Om du vill få ett n-dimensionellt index för geometritypen kan du skapa ett sådant med denna syntax:
CREATE INDEX [indexname] ON [tablename] USING GIST ([geometryfield] gist_geometry_ops_nd);
Att bygga ett spatialt index är en beräkningsintensiv övning. Det blockerar också skrivåtkomst till din tabell under den tid det skapas, så på ett produktionssystem kanske du vill göra det på ett långsammare CONCURRENTLY-medvetet sätt:
CREATE INDEX CONCURRENTLY [indexname] ON [tablename] USING GIST ( [geometryfield] );
Efter att ha byggt ett index är det ibland bra att tvinga PostgreSQL att samla in tabellstatistik, som används för att optimera frågeplaner:
VACUUM ANALYZE [table_name] [(column_name)];
BRIN står för "Block Range Index". Det är en indexmetod för allmänt ändamål som introducerades i PostgreSQL 9.5. BRIN är en förlustindexmetod, vilket innebär att en sekundär kontroll krävs för att bekräfta att en post matchar ett visst sökvillkor (vilket är fallet för alla tillhandahållna spatiala index). Det ger mycket snabbare indexskapande och mycket mindre indexstorlek, med rimlig läsprestanda. Dess primära syfte är att stödja indexering av mycket stora tabeller på kolumner som har en korrelation med sin fysiska plats i tabellen. Förutom spatial indexering kan BRIN påskynda sökningar på olika typer av attributdatastrukturer (heltal, matriser etc.). För mer information se PostgreSQL-manualen.
När en spatial tabell överstiger några tusen rader vill du bygga ett index för att påskynda spatiala sökningar av data. GiST-index är mycket effektiva så länge deras storlek inte överstiger mängden RAM-minne som är tillgängligt för databasen och så länge du har råd med indexets lagringsstorlek och kostnaden för indexuppdatering vid skrivning. I annat fall kan BRIN-index betraktas som ett alternativ för mycket stora tabeller.
Ett BRIN-index lagrar den avgränsande box som omsluter alla geometrier som finns i raderna i en sammanhängande uppsättning tabellblock, ett så kallat blockintervall. När en fråga körs med hjälp av indexet skannas blockområdena för att hitta dem som skär frågans utsträckning. Detta är effektivt endast om data är fysiskt ordnade så att blockintervallens avgränsande rutor har minimal överlappning (och helst är ömsesidigt uteslutande). Det resulterande indexet är mycket litet i storlek, men har vanligtvis sämre läsprestanda än ett GiST-index över samma data.
Att bygga ett BRIN-index är mycket mindre CPU-intensivt än att bygga ett GiST-index. Det är vanligt att ett BRIN-index är tio gånger snabbare att bygga än ett GiST-index över samma data. Och eftersom ett BRIN-index bara lagrar en bounding box för varje intervall av tabellblock, är det vanligt att det använder upp till tusen gånger mindre diskutrymme än ett GiST-index.
Du kan välja hur många block som ska sammanfattas i ett intervall. Om du minskar detta antal blir indexet större, men ger förmodligen bättre prestanda.
För att BRIN ska vara effektivt bör tabelldata lagras i en fysisk ordning som minimerar mängden överlappning av blockutbredningen. Det kan hända att data redan är sorterade på lämpligt sätt (t.ex. om de har laddats från en annan dataset som redan är sorterad i spatial ordning). Annars kan detta åstadkommas genom att sortera data efter en endimensionell spatial nyckel. Ett sätt att göra detta är att skapa en ny tabell sorterad efter geometrivärdena (som i de senaste PostGIS-versionerna använder en effektiv Hilbertkurvor-ordning):
CREATE TABLE table_sorted AS SELECT * FROM table ORDER BY geom;
Alternativt kan data sorteras på plats genom att använda en GeoHash som ett (tillfälligt) index och klustra på det indexet:
CREATE INDEX idx_temp_geohash ON table USING btree (ST_GeoHash( ST_Transform( geom, 4326 ), 20)); CLUSTER table USING idx_temp_geohash;
Syntaxen för att bygga ett BRIN-index på en geometrikolumn
är:
CREATE INDEX [indexname] ON [tablename] USING BRIN ( [geome_col] );
Syntaxen ovan skapar ett 2D-index. Om du vill bygga ett 3D-dimensionellt index använder du den här syntaxen:
CREATE INDEX [indexname] ON [tablename] USING BRIN ([geome_col] brin_geometry_inclusion_ops_3d);
Du kan också få ett 4D-dimensionellt index med hjälp av operatorsklassen 4D:
CREATE INDEX [indexname] ON [tablename] USING BRIN ([geome_col] brin_geometry_inclusion_ops_4d);
Ovanstående kommandon använder standardantalet block i ett intervall, vilket är 128. Om du vill ange antalet block som ska sammanfattas i ett intervall använder du följande syntax
CREATE INDEX [indexname] ON [tablename] USING BRIN ( [geome_col] ) WITH (pages_per_range = [number]);
Tänk på att ett BRIN-index bara lagrar en indexpost för ett stort antal rader. Om din tabell lagrar geometrier med ett blandat antal dimensioner är det troligt att det resulterande indexet kommer att ha dålig prestanda. Du kan undvika denna prestandaförlust genom att välja den operatorsklass som har minst antal dimensioner för de lagrade geometrierna
Datatypen geography
stöds för BRIN-indexering. Syntaxen för att bygga ett BRIN-index på en geografikolumn är:
CREATE INDEX [indexname] ON [tablename] USING BRIN ( [geog_col] );
Syntaxen ovan bygger upp ett 2D-index för geospatiala objekt på sfäroiden.
För närvarande finns endast "inclusion support", vilket innebär att endast operatorerna &&
, ~
och @
kan användas för 2D-fall (för både geometri
och geografi
), och endast operatorn &&&
för 3D-geometrier. Det finns för närvarande inget stöd för kNN-sökningar.
En viktig skillnad mellan BRIN och andra indextyper är att databasen inte underhåller indexet dynamiskt. Ändringar av spatiala data i tabellen läggs helt enkelt till i slutet av indexet. Detta leder till att indexets sökprestanda försämras med tiden. Indexet kan uppdateras genom att utföra en VACUUM
eller genom att använda en specialfunktion brin_summarize_new_values(regclass)
. Av denna anledning kan BRIN vara lämpligast att använda med data som är skrivskyddade eller endast sällan ändras. För mer information se manualen.
Sammanfattningsvis använder vi BRIN för spatiala data:
Indexet byggs upp mycket snabbt och indexets storlek är mycket liten.
Indexfrågetiden är långsammare än för GiST, men kan fortfarande vara mycket acceptabel.
Kräver att tabelldata sorteras i en spatial ordning.
Kräver manuellt indexunderhåll.
Lämpar sig bäst för mycket stora tabeller, med låg eller ingen överlappning (t.ex. punkter), som är statiska eller ändras sällan.
Mer effektiv för frågor som returnerar ett relativt stort antal dataposter.
SP-GiST står för "Space-Partitioned Generalized Search Tree" och är en generisk form av indexering för flerdimensionella datatyper som stöder partitionerade sökträd, t.ex. quad-trees, k-d trees och radix trees (tries). Gemensamt för dessa datastrukturer är att de upprepade gånger delar upp sökrymden i partitioner som inte behöver vara lika stora. Förutom spatial indexering används SP-GiST för att påskynda sökningar på många typer av data, till exempel telefonrouting, ip-routing, substringsökning etc. För mer information se PostgreSQL-manualen.
Liksom GiST-index är SP-GiST-index förlustbringande, i den meningen att de lagrar den avgränsande box som omger spatiala objekt. SP-GiST-index kan betraktas som ett alternativ till GiST-index.
När en GIS-datatabell överstiger några tusen rader kan ett SP-GiST-index användas för att påskynda spatiala sökningar av data. Syntaxen för att bygga ett SP-GiST-index på en "geometri"-kolumn är följande:
CREATE INDEX [indexname] ON [tablename] USING SPGIST ( [geometryfield] );
Syntaxen ovan bygger upp ett 2-dimensionellt index. Ett 3-dimensionellt index för geometritypen kan skapas med hjälp av operatorsklassen 3D:
CREATE INDEX [indexname] ON [tablename] USING SPGIST ([geometryfield] spgist_geometry_ops_3d);
Att bygga ett spatialt index är en beräkningsintensiv operation. Det blockerar också skrivåtkomst till din tabell under den tid det skapas, så på ett produktionssystem kanske du vill göra det på ett långsammare CONCURRENTLY-medvetet sätt:
CREATE INDEX CONCURRENTLY [indexname] ON [tablename] USING SPGIST ( [geometryfield] );
Efter att ha byggt ett index är det ibland bra att tvinga PostgreSQL att samla in tabellstatistik, som används för att optimera frågeplaner:
VACUUM ANALYZE [table_name] [(column_name)];
Ett SP-GiST-index kan påskynda frågor som involverar följande operatorer:
<<, &<, &>, >>, <<|, &<|, |&>, |>>, &&, @>, <@, och ~=, för 2-dimensionella index,
&/&, ~==, @>>, och <<@, för 3-dimensionella index.
Det finns för närvarande inget stöd för kNN-sökningar.
Vanligtvis påskyndar index osynligt dataåtkomst: när ett index har byggts bestämmer PostgreSQL-frågeplaneraren automatiskt när den ska användas för att förbättra frågeprestanda. Men det finns vissa situationer där planeraren inte väljer att använda befintliga index, så frågor slutar använda långsamma sekventiella skanningar istället för ett spatialt index.
Om du upptäcker att dina spatiala index inte används finns det några saker du kan göra:
Granska frågeplanen och kontrollera att din fråga faktiskt beräknar det du behöver. En felaktig JOIN, antingen bortglömd eller till fel tabell, kan oväntat hämta tabellposter flera gånger. För att få fram frågeplanen kör du med EXPLAIN
framför frågan.
Se till att statistik samlas in om antalet och fördelningen av värden i en tabell, så att frågeplaneraren får bättre information för att fatta beslut om indexanvändning. VACUUM ANALYZE beräknar båda.
Du bör regelbundet dammsuga dina databaser ändå. Många PostgreSQL DBA: er kör VACUUM som ett cron-jobb utanför topparna regelbundet.
Om det inte hjälper att dammsuga kan du tillfälligt tvinga planeraren att använda indexinformationen genom att använda kommandot SET ENABLE_SEQSCAN TO OFF;. På så sätt kan du kontrollera om planeraren överhuvudtaget kan generera en indexaccelererad frågeplan för din fråga. Du bör bara använda det här kommandot för felsökning; i allmänhet vet planeraren bättre än du när index ska användas. När du har kört din fråga, glöm inte att köra SET ENABLE_SEQSCAN TO ON; så att planeraren fungerar normalt för andra frågor.
Om SET ENABLE_SEQSCAN TO OFF; hjälper din fråga att köras snabbare är din Postgres sannolikt inte inställd för din maskinvara. Om du tycker att planeraren har fel om kostnaden för sekventiella skanningar jämfört med indexskanningar kan du försöka minska värdet på RANDOM_PAGE_COST
i postgresql.conf
eller använda SET RANDOM_PAGE_COST TO 1.1;. Standardvärdet för RANDOM_PAGE_COST
är 4,0. Prova att ställa in det på 1,1 (för SSD) eller 2,0 (för snabba magnetiska diskar). Om du sänker värdet blir det mer sannolikt att planeraren använder indexskanningar.
Om SET ENABLE_SEQSCAN TO OFF; inte hjälper din fråga kan det bero på att frågan använder en SQL construct som Postgres-planeraren ännu inte kan optimera. Det kan vara möjligt att skriva om frågan på ett sätt som planeraren kan hantera. Till exempel kanske en underfråga med en inline SELECT inte ger en effektiv plan, men kan eventuellt skrivas om med hjälp av en LATERAL JOIN.
Mer information finns i Postgres-manualens avsnitt om Query Planning.