基于 osmchina 数据库的综合业务应用场景实践

osmchina 数据库不仅拥有完整的 33GB 全国 OSM 空间要素,而且预先导入了全国多级行政区划矢量图层(china_provinces 与 map_* 表)。通过 PostGIS 空间函数,我们可以打破数据孤岛,搭建起多种企业级、科研级的空间智能应用。

以下精选整理了 4 种最典型的综合应用场景与具体 SQL 示例。


场景一:省/市/区县级行政区要素聚合与统计分析

痛点与需求

OSM 原生行政区边界复杂且经常变更,难以与国内标准统计年鉴或行政代码(adcode)对齐。通过将 china_provinces(或 map_citys、map_county)与 OSM 要素做空间连接,可以直接按中国行政区划自动聚合各类物理要素。

典型 SQL 示例:统计各省医院与高速公路总里程

SELECT 
    p.name AS 省份名称,
    p.adcode AS 行政区编码,
    -- 统计省内医院数量 (POI 空间包含)
    COUNT(DISTINCT h.osm_id) AS 医院数量,
    -- 统计省内高速公路总里程 (公里)
    ROUND((SUM(ST_Length(ST_Intersection(r.way, p.geom_3857))) / 1000)::numeric, 2) AS 高速总里程_公里
FROM china_provinces p
LEFT JOIN planet_osm_point h 
    ON ST_Contains(p.geom_3857, h.way) 
    AND h.amenity = 'hospital'
LEFT JOIN planet_osm_roads r 
    ON ST_Intersects(p.geom_3857, r.way) 
    AND r.highway = 'motorway'
GROUP BY p.name, p.adcode, p.geom_3857
ORDER BY 高速总里程_公里 DESC NULLS LAST;

场景二:基于 PostGIS 缓冲区的“15 分钟社区便民生活圈”评估

痛点与需求

城市规划中经常评估居住小区或公共交通枢纽周边的公共服务均等化水平。例如以地铁站或大型住宅区为中心,计算其 500 米(步行 5~7 分钟)或 1000 米范围内的生活便民配套(超市、药店、公园绿地)。

典型 SQL 示例:计算某地铁站周边 800 米内的配套设施

WITH station AS (
    -- 选取目标地铁站 (例如:大望路站)
    SELECT osm_id, name, way 
    FROM planet_osm_point 
    WHERE railway = 'subway_entrance' AND name LIKE '%大望路%'
    LIMIT 1
),
station_buffer AS (
    -- 生成 800 米服务半径缓冲区 (EPSG:3857 单位为米)
    SELECT name, ST_Buffer(way, 800) AS geom_buffer
    FROM station
)
SELECT 
    b.name AS 地铁站,
    COUNT(CASE WHEN p.shop IN ('convenience', 'supermarket') THEN 1 END) AS 便捷超市数,
    COUNT(CASE WHEN p.amenity = 'restaurant' THEN 1 END) AS 餐饮设施数,
    COUNT(CASE WHEN p.amenity = 'pharmacy' THEN 1 END) AS 药店诊所数,
    -- 计算缓冲区内公园绿地总覆盖面积 (平方米)
    COALESCE(SUM(ST_Area(ST_Intersection(poly.way, b.geom_buffer))), 0)::int AS 绿化公园面积_平米
FROM station_buffer b
LEFT JOIN planet_osm_point p 
    ON ST_Contains(b.geom_buffer, p.way)
LEFT JOIN planet_osm_polygon poly 
    ON ST_Intersects(b.geom_buffer, poly.way) 
    AND (poly.leisure = 'park' OR poly.landuse = 'grass')
GROUP BY b.name;

场景三:动态生成 Mapbox Vector Tile (MVT) 矢量瓦片服务

痛点与需求

现代 WebGIS 架构(如 Mapbox GL JS、MapLibre、Cesium)推荐采用矢量切片。结合 PostGIS 原生的 ST_AsMVT 与 ST_TileEnvelope 函数,后端(Node.js / Python FastAPI / Go)可以直接利用 osmchina 动态提供矢量切片接口,无需离线预切片或借助第三方 TileServer。

典型 SQL 示例:实现 Z/X/Y 动态切片端点

-- 传入参数:z (缩放级别), x (列号), y (行号)
-- 例如生成等级道路图层瓦片
WITH bbox AS (
    -- 根据墨卡托瓦片编号自动计算边界四至多边形
    SELECT ST_TileEnvelope(14, 13440, 6210) AS tile_geom
),
tile_data AS (
    SELECT 
        l.osm_id,
        l.name,
        l.highway,
        ST_AsMVTGeom(l.way, b.tile_geom, 4096, 64, true) AS geom
    FROM planet_osm_line l, bbox b
    WHERE l.way && b.tile_geom AND l.highway IS NOT NULL
)
SELECT ST_AsMVT(tile_data, 'roads', 4096, 'geom') AS mvt_binary
FROM tile_data;

场景四:生态红线与水环境敏感区空间相交检测

痛点与需求

在水利、环保与规划建设中,工程项目选址需要快速判断其规划选址点或拟建路线是否跨越了主要河道水系、湿地生态保护区,或计算沿河 200 米缓冲敏感带内的土地覆盖情况。

典型 SQL 示例:长江/主要干流两岸 1000 米生态缓冲区土地利用分析

WITH river_belt AS (
    -- 提取重要水系干流并生成 1000 米水生态保护红线走廊
    SELECT ST_Union(ST_Buffer(way, 1000)) AS buffer_geom
    FROM planet_osm_line
    WHERE waterway IN ('river', 'canal') AND name LIKE '%长江%'
)
SELECT 
    p.landuse AS 用地类型,
    COUNT(*) AS 宗地斑块数量,
    ROUND(SUM(ST_Area(ST_Intersection(p.way, b.buffer_geom)))::numeric / 1000000, 2) AS 占地总面积_平方公里
FROM river_belt b
JOIN planet_osm_polygon p 
    ON ST_Intersects(b.buffer_geom, p.way)
WHERE p.landuse IS NOT NULL
GROUP BY p.landuse
ORDER BY 占地总面积_平方公里 DESC;

五、总结与性能调优建议

  1. 善用 && 空间包围盒预筛选:PostGIS 的 && 操作符能充分触发 GiST 索引,大幅降低耗时。
  2. 区分表的使用层级:全域宏观渲染优先选用 planet_osm_roads,局部微观分析再下钻到 planet_osm_line。
  3. 坐标投影统一:OSM 表为 EPSG:3857(单位米),外部经纬度数据(EPSG:4326)建议通过 ST_Transform(geom, 3857) 计算或常驻持久化投影列。