
PostGIS gebruiken voor BAG-data in RD New
PostGIS voegt ruimtelijke typen, indexen en functies toe aan PostgreSQL. Een BAG-extract laadt u met ogr2ogr uit de PDOK OGC API in een tabel in RD New (EPSG:28992), waarna een GiST-index ruimtelijke vragen snel maakt. Hieronder staan getest commando's op PostGIS 3.6.4, met een gemeten verschil tussen een query met en zonder index.

Wat is PostGIS en welke versie is actueel?
PostGIS is een extensie voor de database PostgreSQL. Het project beschrijft zichzelf zo:
PostGIS extends the capabilities of the PostgreSQL relational database by adding support for storing, indexing, and querying geospatial data.
Bron: postgis.net, gelezen op 11 oktober 2026. Een extensie betekent dat u PostgreSQL blijft gebruiken voor beheer, back-ups en rechten, en dat PostGIS daar kolomtypen en functies aan toevoegt.
| Eigenschap | Waarde |
|---|---|
| Beheerder | PostGIS-project, repository postgis/postgis op GitHub |
| Licentie | GPL-2.0 (GNU General Public License versie 2) |
| Actuele stabiele versie | 3.6.4, uitgebracht op 8 juni 2026 volgens het NEWS-bestand |
| In voorbereiding | 3.7.0; release candidate 2 aangekondigd op 8 september 2026, op 12 oktober 2026 nog geen definitieve release |
| Eisen van 3.7.0 | GEOS 3.10 of hoger en PostgreSQL 14 tot en met 19beta3 |
| Coördinaatstelsels | Elk stelsel uit de PROJ-database, waaronder EPSG:28992 (RD New) |
| Testomgeving voor deze pagina | PostGIS 3.6.4 op PostgreSQL 17.9 met GEOS 3.15.0 en PROJ 9.8.1 |
PostGIS is de aangewezen plek voor ruimtelijke data die meerdere gebruikers raken of die u aan andere systemen koppelt. Voor een eenmalige analyse is een bestand vaak genoeg, zie Python voor GIS.
Hoe laadt u een BAG-extract met ogr2ogr?
U leest de BAG OGC API van PDOK met het OAPIF-stuurprogramma van ogr2ogr en schrijft de resultaten naar PostGIS. De BAG slaat zijn geometrie al op in RD New, dus u hoeft niet om te rekenen. Het gaat om een extract: de API is bedoeld voor een gebied, niet voor een heel land.
| Eigenschap | Waarde |
|---|---|
| Eigenaar | Kadaster, via PDOK |
| Basis-URL | https://api.pdok.nl/kadaster/bag/ogc/v2 |
| Collecties | adres, ligplaats, pand, standplaats, verblijfsobject en woonplaats |
| Opslagstelsel | EPSG:28992; ook CRS84, EPSG:3857 en EPSG:4258 beschikbaar |
| Licentie | Public Domain Mark 1.0 |
| Volledige download | Atom-downloadservice met GeoPackage, https://service.pdok.nl/lv/bag/atom/bag.xml |
De volgende commando's laden een vierkante kilometer rond het centrum van Amersfoort. De openingsoptie PAGE_SIZE houdt elk verzoek klein; de standaard is volgens de GDAL-documentatie 1.000.
# Panden en verblijfsobjecten in een vierkante kilometer rond de Onze Lieve Vrouwetoren in Amersfoort
API="OAPIF:https://api.pdok.nl/kadaster/bag/ogc/v2"
ogr2ogr -f PostgreSQL "PG:dbname=bag" "$API" pand -spat 154500 462700 155500 463700 -spat_srs EPSG:28992 -t_srs EPSG:28992 -nlt PROMOTE_TO_MULTI -lco GEOMETRY_NAME=geom -overwrite -oo PAGE_SIZE=200
ogr2ogr -f PostgreSQL "PG:dbname=bag" "$API" verblijfsobject -spat 154500 462700 155500 463700 -spat_srs EPSG:28992 -t_srs EPSG:28992 -lco GEOMETRY_NAME=geom -overwrite -oo PAGE_SIZE=200
Resultaat op 11 oktober 2026, herhaald op 12 oktober met GDAL 3.13.3: 3.105 panden en 6.070 verblijfsobjecten, voor beide lagen samen tussen 13 en 34 seconden. De panden kwamen als geometry(MultiPolygon,28992), de verblijfsobjecten als geometry(Point,28992), elk met een GiST-index. Alle 3.105 geometrieën waren geldig volgens ST_IsValid. Zet de opties van -spat niet in een shellvariabele: zsh, de standaardshell op macOS, splitst zo'n variabele niet in losse argumenten, en ogr2ogr toonde in de test dan alleen zijn gebruiksinstructie.
Een grotere selectie ging mis: een gebied van 2 bij 1,5 kilometer eindigde met de standaardpaginagrootte in HTTP-status 500 (time-out), en met pagina's van 200 was het na acht minuten nog niet klaar. Voor een hele gemeente of heel Nederland gebruikt u de Atom-download. Meer over de dataset staat op BAG en over PDOK als aanbieder in het overzicht van open geodata. Hoe de API-standaard werkt, leest u bij WFS en OGC API Features.
Hoe maakt u een ruimtelijke index in PostGIS?
U maakt een GiST-index op de geometriekolom en draait daarna ANALYZE. Ogr2ogr deed dat hier al: de tabel pand had na het laden de index pand_geom_geom_idx. Handmatig doet u hetzelfde met CREATE INDEX pand_geom_idx ON pand USING GIST (geom);. De PostGIS-handleiding legt het nut uit:
Without indexing, a search for features requires a sequential scan of every record in the database.
Bron: PostGIS-handleiding, hoofdstuk over databasebeheer, gelezen op 11 oktober 2026. Het verschil is op 3.105 rijen klein maar meetbaar. Dezelfde query, alle panden binnen 100 meter van het RD-punt (155000, 463000), gaf de volgende plannen.
-- zonder index (index tijdelijk verwijderd binnen een transactie)
Aggregate (actual rows=1 loops=1)
-> Seq Scan on pand (actual rows=119 loops=1)
Filter: st_dwithin(geom, '...'::geometry, '100'::double precision)
Rows Removed by Filter: 2986
Execution Time: 3.895 ms
-- met de GiST-index
Aggregate (actual rows=1 loops=1)
-> Bitmap Heap Scan on pand (actual rows=119 loops=1)
Filter: st_dwithin(geom, '...'::geometry, '100'::double precision)
Rows Removed by Filter: 37
-> Bitmap Index Scan on pand_geom_geom_idx (actual rows=156 loops=1)
Index Cond: (geom && st_expand('...'::geometry, '100'::double precision))
Execution Time: 0.356 ms
Over vijf herhalingen op 12 oktober 2026 lag de uitvoeringstijd met index tussen 0,23 en 1,1 milliseconde en zonder index tussen 3,9 en 132 milliseconden, op een laptop die ook andere taken draaide. Dat zijn geen benchmarkcijfers; de orde van grootte is het punt. Het patroon telt: de index levert kandidaten op uit een omhullende rechthoek, en ST_DWithin controleert daarna de werkelijke afstand. De documentatie van ST_DWithin zegt het zo:
This function call includes a bounding box comparison that makes use of any indexes that are available on the geometries.
Welke query-voorbeelden werken op BAG-data?
Drie patronen komen telkens terug: dichtstbijzijnde objecten zoeken, objecten aan elkaar koppelen en coördinaten omrekenen. Alle drie draaiden op de tabellen hierboven. Het eerste voorbeeld zoekt panden dichtbij een punt en sorteert op afstand met de operator <->.
-- panden binnen 50 meter van een punt, dichtstbijzijnde eerst
SELECT identificatie, bouwjaar, round(ST_Area(geom)::numeric, 1) AS m2
FROM pand
WHERE ST_DWithin(geom, ST_SetSRID(ST_MakePoint(155000, 463000), 28992), 50)
ORDER BY geom <-> ST_SetSRID(ST_MakePoint(155000, 463000), 28992)
LIMIT 5;
identificatie | bouwjaar | m2
------------------+----------+-------
0307100000333887 | 1445 | 211.0
0307100000379020 | 1920 | 90.1
0307100000371329 | 1800 | 29.1
0307100000536538 | 1922 | 8.6
0307100000372777 | 2004 | 54.4
Het tweede telt per pand de verblijfsobjecten in de extract, en vergelijkt dat met het aantal dat de BAG zelf bij het pand vermeldt.
-- verblijfsobjecten per pand, via een ruimtelijke join
SELECT p.identificatie, p.aantal_verblijfsobjecten AS bag_aantal, count(v.*) AS in_extract
FROM pand p
JOIN verblijfsobject v ON ST_Within(v.geom, p.geom)
WHERE p.status = 'Pand in gebruik' AND p.aantal_verblijfsobjecten > 20
GROUP BY 1, 2
ORDER BY 2 DESC
LIMIT 5;
identificatie | bag_aantal | in_extract
------------------+------------+------------
0307100000314600 | 272 | 272
0307100000351286 | 128 | 128
0307100000374052 | 97 | 97
0307100000343270 | 86 | 18
0307100000376537 | 77 | 77
Het vierde pand heeft 86 verblijfsobjecten in de BAG maar 18 in de extract. De rest ligt buiten het gekozen vierkant. Een extract met een rechthoekig gebied knipt dus objecten door, en tellingen per pand zijn alleen geldig voor panden die er helemaal in liggen. Dat is geen fout in de query maar een eigenschap van de selectie.
Het derde voorbeeld rekent een WGS84-punt om naar RD. Het resultaat wijkt minder dan een millimeter af van (155000, 463000) en is gelijk aan wat pyproj en proj4js met de juiste definitie geven.
-- WGS84 naar RD, met dezelfde PROJ-bibliotheek als pyproj
SELECT ST_AsText(ST_Transform(ST_SetSRID(ST_MakePoint(5.3872035, 52.1551723), 4326), 28992));
POINT(154999.9995416017 463000.00031318853)
De adresgegevens zitten als tekstkolommen in verblijfsobject, zoals postcode, huisnummer en openbare_ruimte_naam. Een snelle check op een enkel adres kan ook zonder database met de BAG-adrescheck.
Welke valkuilen kent PostGIS met RD en BAG?
Vier valkuilen zijn gemeten, de rest volgt uit de documentatie.
- ST_Distance in de WHERE-clausule.
ST_Distance(geom, punt) < 100gebruikte de index niet en las de hele tabel. GebruikST_DWithin. De PostGIS-documentatie noemtST_Distanceook zelf niet-indexeerbaar in haar voorbeeld. - Een functie om de kolom.
ST_DWithin(ST_Transform(geom, 4326), ...)leidde ook tot een volledige tabelscan. Reken liever het punt om naar het stelsel van de kolom dan de kolom naar het stelsel van het punt. - Het verkeerde SRID. Een punt met SRID 4326, of een punt zonder SRID maar met graden als coördinaten, gaf tegen de RD-kolom in de test met de GiST-index stil nul rijen. Een RD-punt zonder SRID gaf wel meteen de fout Operation on mixed SRID geometries, en met de index uitgeschakeld gaven ook de eerste twee die fout (PostgreSQL 17, PostGIS 3.6.4, herhaald op 12 oktober 2026). Of u een fout ziet, hangt dus af van het queryplan. Zet altijd SRID 28992 op uw punten.
- Eenheden. Met
geometryin RD zijn afstanden meters, in WGS84 graden. De handleiding noemt voorgeographymeters als eenheid. - Kolomnamen. De BAG-API levert kolommen met een punt in de naam:
pand.hrefinverblijfsobjectenverblijfsobject.hrefinpand. Zet die tussen dubbele aanhalingstekens, of laat ze bij het laden weg.
Na een grote import draait u ANALYZE zodat de planner de juiste keuzes maakt. Hoe u zo'n database beheert en hostelt, staat bij GIS-beheer en hosting.
Wanneer kiest u PostGIS niet?
PostGIS loont niet als er één gebruiker is die een eenmalige analyse draait. Dan volstaat een GeoPackage met Python voor GIS, en bespaart u het beheer van een databaseserver. Over het bestandsformaat leest u op GeoPackage, en over de conversieprogramma's op GDAL.
Ook als gegevens alleen worden getoond op een kaart en nooit veranderen, is een database niet nodig. Vooraf gebouwde tegels of bestanden achter een webserver zijn eenvoudiger te beheren en goedkoper te hosten. PostGIS komt in beeld bij bewerkingen door meerdere gebruikers, bij koppelingen met andere systemen en bij query's over grote bestanden.
Wie een open data-platform of dataplatform bouwt, heeft meestal beide nodig: PostGIS voor het beheer en een API voor het delen. Dat laatste doet bijvoorbeeld pygeoapi. TechinFlow levert zelf dataplatforms en heeft dus belang bij deze keuze, daarom zijn de afwegingen hier met bronnen onderbouwd.
Veelgestelde vragen
Welke versie van PostGIS is actueel?
Op 12 oktober 2026 is 3.6.4 de laatste stabiele versie, uitgebracht op 8 juni 2026. Van versie 3.7.0 is op 8 september 2026 release candidate 2 aangekondigd; die versie vraagt volgens het NEWS-bestand GEOS 3.10 of hoger en PostgreSQL 14 tot en met 19beta3. PostGIS valt onder de GPL-2.0.
Hoe krijg ik de hele BAG van Nederland in PostGIS?
Niet via de OGC API. Die is bedoeld voor een gebied en gaf bij een te groot gebied een time-out. PDOK biedt de BAG als GeoPackage via een Atom-downloadservice. Dat bestand laadt u met ogr2ogr in PostGIS. Plan voldoende schijfruimte en tijd voor het laden en voor de indexen.
Is een GiST-index altijd sneller?
Niet altijd. Bij een kleine tabel of een query die het grootste deel van de rijen nodig heeft, kiest de planner soms bewust een volledige scan. In de test op 3.105 panden was de indexquery in elke herhaling sneller, met een verschil van minstens een factor tien. Controleer met EXPLAIN ANALYZE of uw query de index gebruikt.
Moet ik mijn geodata in RD of in WGS84 opslaan?
Sla op in het stelsel van de bron, bij de BAG is dat RD New (EPSG:28992), en reken om bij uitlevering. In RD zijn afstanden en oppervlakten in meters, wat rekenen eenvoudig maakt. Voor webkaarten in WGS84 of Web Mercator rekent u om met ST_Transform.
Is PostGIS geschikt voor een gemeentelijk dataplatform?
Ja, als basis voor ruimtelijke data die meerdere gebruikers raakt. Het is open source, draait op PostgreSQL en praat met QGIS, GDAL en Python. Een dataplatform vraagt daarnaast om beheer, back-ups, toegangsregels en een API, en die horen bij het ontwerp van het geheel.
Bronnen
- PostGIS — postgis.net (gelezen op )
- PostGIS-handleiding — Spatial indexes (databasebeheer) (gelezen op )
- PostGIS-handleiding — ST_DWithin (gelezen op )
- GitHub — postgis/postgis (tags, NEWS en COPYING) (gelezen op )
- PostGIS — nieuws (3.7.0rc2, 8 september 2026) (gelezen op )
- PDOK — BAG OGC API v2 (gelezen op )
- PDOK — Basisregistratie Adressen en Gebouwen (downloadservice) (gelezen op )
- GDAL — OGC API Features (OAPIF) driver (gelezen op )
Meer over TechinFlow
Een nieuw bureau in Haarlem voor maatwerk software, GIS en dataplatforms op open standaarden.
Een vraag of opdracht?
Vertel kort wat er speelt en voor welke organisatie. We reageren per e-mail.
Stuur een bericht