DEV Community

Kanahiro Iguchi for MIERUNE

Posted on • Edited on

Comparing PostGIS-backend Vectortile servers: tegola/martin/pg_tileserv

Abstract

In ordinary cases, vectortiles are statically served as files converted from GeoJSON or other datasources. This is the best way to serve tiles in terms of performances and costs for servers but there are some typical problems.

  • Need computing costs for converting, this can be a bigger problem when a number of tiles is huger.
  • Impossible to serve data equal to database.

Therefore, it is very important to be able to dynamically serve tiles directly from DB. Offcourse, in this approach has other challenges such as performances so you need to consider which approach should be taken and why, how.

There are some implementations in PostGIS-backend Vectortile server in mid 2022. These can be used to serve vectortiles from PostGIS tables.

martin and pg_tileserv is based on ST_AsMVT in PostGIS functions and t-rex and tegola are not. This is because martin and pg_tileserv are newer than others. In this article, I compared tegola, martin and pg_tileserv.

Setting servers

PostgreSQL

First, let's launch PostGIS and insert sample data, using Docker…

 postgis: image: kartoza/postgis:12.4 environment: - POSTGRES_USER=docker - POSTGRES_PASS=docker - POSTGRES_DB=postgres ports: - "5432:5432" volumes: - postgis-data:/var/lib/postgresql - ./postgres:/usr/src/app networks: - default healthcheck: test: [ "CMD-SHELL", "pg_isready" ] interval: 10s timeout: 5s retries: 5 
Enter fullscreen mode Exit fullscreen mode

launch PostgreSQL...

 docker-compose up -d postgis 
Enter fullscreen mode Exit fullscreen mode

Next, get and insert data. I used geofabrik shapefiles.

 wget https://download.geofabrik.de/asia/japan/kanto-latest-free.shp.zip unzip kanto-latest-free.shp.zip ogr2ogr PG:postgresql://docker:docker@localhost:5432/postgres gis_osm_roads_free_1.shp ogr2ogr PG:postgresql://docker:docker@localhost:5432/postgres gis_osm_buildings_a_free_1.shp -nlt MultiPolygon 
Enter fullscreen mode Exit fullscreen mode

Then, you can see tables in PostgreSQL.

 SELECT * FROM gis_osm_roads_free_1 LIMIT 10; SELECT * FROM gis_osm_buildings_a_free_1 LIMIT 10; 
Enter fullscreen mode Exit fullscreen mode

tegola

writting compose.yml...

 tegola: image: gospatial/tegola ports: - "8080:8080" depends_on: postgis: condition: service_healthy volumes: - ./tegola:/opt/tegola_config command: --config /opt/tegola_config/config.toml serve networks: - default 
Enter fullscreen mode Exit fullscreen mode

tegola uses config.toml to define settings how generate and serve vectortiles, as following

 # /tegola/config.toml [webserver] port = ":8080" CORSAllowedOrigin = "*" # register data providers [[providers]] name = "japan" # provider name is referenced from map layers (required) type = "postgis" # the type of data provider. currently only supports postgis (required) host = "postgis" # postgis database host (required) port = 5432 # postgis database port (required) database = "postgres" # postgis database name (required) user = "docker" # postgis database user (required) password = "docker" # postgis database password (required) srid = 4326 # The default srid for this provider. If not provided it will be WebMercator (3857) [[providers.layers]] name = "roads" geometry_fieldname = "wkb_geometry" id_fieldname = "ogc_fid" tablename = "gis_osm_roads_free_1" [[providers.layers]] name = "buildings" geometry_fieldname = "wkb_geometry" id_fieldname = "ogc_fid" tablename = "gis_osm_buildings_a_free_1" [[maps]] name = "japan" center = [139.72120, 35.73273, 11.0] # set the center of the map so the user is auto navigated to Bonn [[maps.layers]] provider_layer = "japan.buildings" min_zoom = 5 max_zoom = 20 [[maps.layers]] provider_layer = "japan.roads" min_zoom = 5 max_zoom = 20 
Enter fullscreen mode Exit fullscreen mode

With these settings, vectortiles will be served as http://localhost:8080/maps/japan/{z}/{x}/{y}.vector.pbf.

martin

compose

 martin: image: urbica/martin restart: unless-stopped ports: - 3000:3000 depends_on: postgis: condition: service_healthy networks: - default volumes: - ./martin:/opt/martin_config command: martin --config /opt/martin_config/config.yaml 
Enter fullscreen mode Exit fullscreen mode

martin takes a similar approach to tegola, using setting file in yml.

 # The socket address to bind [default: 0.0.0.0:3000] listen_addresses: '0.0.0.0:3000' # Database connection string connection_string: 'postgres://docker:docker@postgis/postgres' # Maximum connections pool size [default: 20] pool_size: 20 # Connection keep alive timeout [default: 75] keep_alive: 75 # Number of web server workers worker_processes: 8 # If a spatial table has SRID 0, then this default SRID will be used as a fallback default_srid: 4326 # Enable watch mode watch: false # Trust invalid certificates. This introduces significant vulnerabilities, and should only be used as a last resort. danger_accept_invalid_certs: true # Associative arrays of table sources table_sources: public.buildings: # Table source id (required) id: public.gis_osm_buildings_a_free_1 # Table schema (required) schema: public # Table name (required) table: gis_osm_buildings_a_free_1 # Geometry SRID (required) srid: 4326 # Geometry column name (required) geometry_column: wkb_geometry # Feature id column name id_column: ogc_fid # An integer specifying the minimum zoom level minzoom: 0 # An integer specifying the maximum zoom level. MUST be >= minzoom maxzoom: 30 # The maximum extent of available map tiles. Bounds MUST define an area # covered by all zoom levels. The bounds are represented in WGS:84 # latitude and longitude values, in the order left, bottom, right, top. # Values may be integers or floating point numbers. bounds: [-180.0, -90.0, 180.0, 90.0] # Tile extent in tile coordinate space extent: 4096 # Buffer distance in tile coordinate space to optionally clip geometries buffer: 64 # Boolean to control if geometries should be clipped or encoded as is clip_geom: true # Geometry type geometry_type: GEOMETRY # List of columns, that should be encoded as tile properties (required) properties: ogc_fid: integer name: string fclass: string public.roads: id: public.gis_osm_roads_free_1 schema: public table: gis_osm_roads_free_1 srid: 4326 geometry_column: wkb_geometry id_column: ogc_fid minzoom: 0 maxzoom: 30 bounds: [-180.0, -90.0, 180.0, 90.0] extent: 4096 buffer: 64 clip_geom: true geometry_type: GEOMETRY properties: ogc_fid: integer name: string fclass: string maxspeed: smallint 
Enter fullscreen mode Exit fullscreen mode

Vectortiles will be served as http://localhost:3000/public.roads,public.buildings/{z}/{x}/{y}.pbf.

pg_tileserv

compose

 pg_tileserv: image: pramsey/pg_tileserv container_name: pg_tileserv environment: - DATABASE_URL=postgres://docker:docker@postgis/postgres depends_on: - postgis ports: - 7800:7800 
Enter fullscreen mode Exit fullscreen mode

pg_tileserv can be launched without config files. Tables are automatically loaded.

Vectortiles will be served as http://localhost:7800/public.gis_osm_buildings_a_free_1,public.gis_osm_roads_free_1/{z}/{x}/{y}.vector.pbf.

Comparing

Now we can launch vectortile server!

 docker compose up 
Enter fullscreen mode Exit fullscreen mode

In QGIS, you can get tiles as following...

  1. add vectortile source
  2. zoom into a area data exists in
  3. add vectortile layer

Image description

Image description

Image description

Then you can see no difference between three servers in terms of apperance because we use same database, but there should be a big differnce in performances. martin and pg_tileserv should be much faster than tegola.

Image description

why different?

I'm not familiar with details in implementation of tegola and martin/pg_tileserv but I guess it is because martin/pg_tileserv uses ST_AsMVT and tegola doesn't.

As far as I digged, ST_AsMVT was implemented in 2018 first, and the performance improved in 2019.

Actually newest version of tegola seems to support ST_AsMVT but I couldn't work it, troubled in settings.

Besides, martin is clearly faster than pg_tileserv. The reason of this difference is less sure than between tegola and martin/pg_tileserv but martin uses Actix-webserver, which is one of the fastest server(https://www.techempower.com/benchmarks/#section=data-r21)) and this could explain a certain extent of the difference.

Conclusion

  • martin is the fastest PostGIS-backend vectortile server.
  • pg_tileserv is second but easy config and rich functions.

Full Codes

https://github.com/Kanahiro/postgis-tileservers-compare

Top comments (0)