Geospatial
Databend 提供两种数据类型来存储空间数据:
GEOMETRY:基于平面坐标(默认 SRID 为 0,也可指定任意 SRID),适用于局部或投影坐标系的场景。GEOGRAPHY:基于球面坐标(WGS 84,SRID 4326),会对经纬度进行校验,适用于全球范围的场景。
这两种类型都将坐标以 IEEE 754 Float64 格式存储在 EWKB 中,支持从 Point 到 GeometryCollection 的所有常见几何对象,能够输出 WKT/WKB/GeoJSON 格式,并支持通过 ST_TRANSFORM 等函数进行坐标投影转换。
数据类型
GEOMETRY
- 使用笛卡尔坐标系,非常适合校园、城市或省份等可以使用平面数学计算的场景。
- 默认 SRID 为 0;在创建列或写入数据时可以指定其他 SRID。
- 支持大多数空间操作符,并可通过
ST_TRANSFORM转换为其他投影供下游使用。
GEOGRAPHY
- 存储 WGS 84 (SRID 4326) 标准的经纬度对;超出 [-180°, 180°] / [-90°, 90°] 范围的值将被拒绝。
- 推荐用于需要椭球公式计算的跨洲或全球距离/面积计算。
- 当需要使用平面算法时,可以转换为 GEOMETRY 类型。
| 特性 | GEOMETRY | GEOGRAPHY |
|---|---|---|
| 坐标系 | 笛卡尔 (平面) | 椭球 (球面) |
| SRID | 0 (默认) 或自定义 | 仅限 4326 (WGS 84) |
| X / Y 含义 | 平面上的 X, Y | 球面上的经度, 纬度 |
| 边线含义 | 平面直线 | 大圆弧 (球面最短路径) |
| 主要用途 | 局部 / 投影数据 (如城市、建筑) | 全球数据 (如 GPS 轨迹、航线) |
精度与坐标控制
- 全程双精度:
ST_MAKEPOINT和ST_GEOMETRYFROMEWKT等函数接收Float64值并以 EWKB 格式持久化,从而保留坐标的原始精度。 - SRID 行为:GEOMETRY 保留你指定的任意 SRID(默认为 0),而 GEOGRAPHY 固定为 SRID 4326 并拒绝其他 SRID。
- 坐标安全:GEOGRAPHY 的输入会经过
check_point检查,确保经纬度在 [-180°, 180°] / [-90°, 90°] 范围内。 - 投影转换:
ST_TRANSFORM可以转换 GEOMETRY 的 SRID(例如 4326 → 3857),或者将 GEOGRAPHY 数据转换为平面系统以便进行后续处理。
支持的对象类型
| 对象类型 | 描述与示例 | 精度说明 |
|---|---|---|
| Point | 单个坐标点,例如 POINT(113.98765432109876 23.456789012345678) | 每个坐标存储为 Float64,保留约 15–16 位有效数字。 |
| LineString | 连通路径,例如 LINESTRING(10 20, 30 40, 50 60) | 每个顶点都使用相同的双精度存储,因此计算出的长度依赖于原始值的精度。 |
| Polygon | 闭合区域,例如 POLYGON((10 20, 30 40, 50 60, 10 20)) | 所有环共享 Float64 顶点,保证多边形边缘在面积/包含测试中的精度。 |
| MultiPoint | 多点集合,例如 MULTIPOINT((10 20), (30 40)) | 集合中的每个点都继承了独立点的双精度存储特性。 |
| MultiLineString | 多路径集合,例如 MULTILINESTRING((10 20, 30 40), (50 60, 70 80)) | 每个顶点都保持精度,确保长度或交集计算准确。 |
| MultiPolygon | 多区域集合,例如 MULTIPOLYGON(((10 20, 30 40, 50 60, 10 20)), ((15 25, 25 35, 35 45, 15 25))) | 每个多边形的坐标保持 Float64,因此合并区域/重叠部分保留完整精度。 |
| GeometryCollection | 混合对象集合,例如 GEOMETRYCOLLECTION(POINT(10 20), LINESTRING(10 20, 30 40)) | 无论几何类型如何,成员都保留其原生的双精度坐标。 |
输出格式
Databend 将空间值持久化为 EWKB,但也提供多种输出格式。你可以设置 geometry_output_format 会话参数(默认:WKT)或调用显式转换函数:
- WKT / EWKT – 文本表示;EWKT 会添加 SRID 前缀(例如
SRID=4326;POINT(-44.3 60.1))。 - WKB / EWKB – 紧凑的二进制格式,便于与其他 GIS 运行时互操作。
- GeoJSON – JSON 表示,适用于 Web 地图和 API。
SET geometry_output_format = 'GeoJSON';
SELECT ST_ASWKB(geo), ST_ASEWKT(geo), ST_ASGEOJSON(geo) FROM ...;
函数
查看完整的空间函数列表:
示例
以下每个示例展示了一种对象类型、它解决的场景、生成它的 SQL 以及示例结果表。CAST('…' AS GEOMETRY) 用于解析内联 WKT 字面量,方便你在不创建表的情况下进行实验。
Point — 定位单个传感器
场景:存储 IoT 设备生成的精确经纬度,并同时展示 GeoJSON 和数值坐标。
SELECT
ST_ASGEOJSON(pt) AS sensor_geojson,
ST_X(pt) AS lon,
ST_Y(pt) AS lat
FROM (SELECT CAST('POINT(113.98765432109876 23.456789012345678)' AS GEOMETRY) AS pt);
┌──────────────────────────────────────────────────────────────────────────────┬──────────────────────┬──────────────────────┐
│ sensor_geojson │ lon │ lat │
├──────────────────────────────────────────────────────────────────────────────┼──────────────────────┼──────────────────────┤
│ {"type":"Point","coordinates":[113.98765432109876,23.456789012345677]} │ 113.98765432109876 │ 23.456789012345677 │
└──────────────────────────────────────────────────────────────────────────────┴──────────────────────┴──────────────────────┘
LineString — 描述路径
场景:记录一条简单的驾驶路线,并以坐标单位测量其长度。
SELECT
ST_ASWKT(route) AS road_segment,
ST_LENGTH(route) AS segment_length
FROM (SELECT CAST('LINESTRING(10 20, 30 40, 50 60)' AS GEOMETRY) AS route);
┌──────────────────────────────────────────────────────────────┬────────────────────┐
│ road_segment │ segment_length │
├──────────────────────────────────────────────────────────────┼────────────────────┤
│ LINESTRING(10 20,30 40,50 60) │ 56.568542495 │
└──────────────────────────────────────────────────────────────┴────────────────────┘
Polygon — 捕获区域或地理围栏
场景:为设施定义一个矩形地理围栏,读取其 SRID 信息,并计算其面积。
SELECT
ST_ASEWKT(area) AS ewkt_polygon,
ST_AREA(area) AS area_units
FROM (SELECT CAST('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))' AS GEOMETRY) AS area);
┌──────────────────────────────────────────────────────────────┬──────────────┐
│ ewkt_polygon │ area_units │
├──────────────────────────────────────────────────────────────┼──────────────┤
│ POLYGON((0 0,0 10,10 10,10 0,0 0)) │ 100 │
└──────────────────────────────────────────────────────────────┴──────────────┘
MultiPoint — 标记多个地点
场景:将三个服务亭的坐标保存在一起,并报告 GeoJSON 数据和总数。
SELECT
ST_ASGEOJSON(places) AS places_geojson,
ST_NUMPOINTS(places) AS total_sites
FROM (SELECT CAST('MULTIPOINT((10 20), (30 40), (50 60))' AS GEOMETRY) AS places);
┌──────────────────────────────────────────────────────────────┬──────────────┐
│ places_geojson │ total_sites │
├──────────────────────────────────────────────────────────────┼──────────────┤
│ {"type":"MultiPoint","coordinates":[[10,20],[30,40],[50,60]]} │ 3 │
└──────────────────────────────────────────────────────────────┴──────────────┘
MultiLineString — 表示平行线
场景:组合两条平行的路段,将其读取为 WKT,并使用 ST_NUMPOINTS 统计总顶点数。
SELECT
ST_ASWKT(lines) AS multiline_wkt,
ST_NUMPOINTS(lines) AS vertex_count
FROM (SELECT CAST('MULTILINESTRING((10 20, 30 40), (50 60, 70 80))' AS GEOMETRY) AS lines);
┌──────────────────────────────────────────────────────────────┬──────────────┐
│ multiline_wkt │ vertex_count │
├──────────────────────────────────────────────────────────────┼──────────────┤
│ MULTILINESTRING((10 20,30 40),(50 60,70 80)) │ 4 │
└──────────────────────────────────────────────────────────────┴──────────────┘
MultiPolygon — 覆盖不相连的区域
场景:表示两个不相连的服务区域,并计算总面积。
SELECT
ST_ASGEOJSON(zones) AS zones_geojson,
ST_AREA(zones) AS total_area
FROM (
SELECT CAST('MULTIPOLYGON(((0 0, 0 10, 10 10, 10 0, 0 0)), ((20 0, 20 10, 30 10, 30 0, 20 0)))' AS GEOMETRY) AS zones
);
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬──────────────┐
│ zones_geojson │ total_area │
├─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────┤
│ {"type":"MultiPolygon","coordinates":[[[[0,0],[0,10],[10,10],[10,0],[0,0]]],[[[20,0],[20,10],[30,10],[30,0],[20,0]]]]} │ 200 │
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴──────────────┘
GeometryCollection — 混合不同形状
场景:将地标标记及其连接路径保存在一起,展示混合的 GeoJSON 和最大维度。
SELECT
ST_ASGEOJSON(feature) AS feature_geojson,
ST_DIMENSION(feature) AS max_dimension
FROM (
SELECT CAST('GEOMETRYCOLLECTION(POINT(10 20), LINESTRING(10 20, 30 40))' AS GEOMETRY) AS feature
);
┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬───────────────┐
│ feature_geojson │ max_dimension │
├────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼───────────────┤
│ {"type":"GeometryCollection","geometries":[{"type":"Point","coordinates":[10,20]},{"type":"LineString","coordinates":[[10,20],[30,40]]}]} │ 1 │
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴───────────────┘

