基于GeoSOT编码的多图层穿越查询

在海量空间数据管理系统中,经常用到多图层查询的应用,比如查看指定范围内有哪些图层,各图层在此区域大约有多少对象并获取属性相关的统计数据。 传统的实现方式,是对所有图层进行范围过滤,尽管有各图层有空间索引进行加速,随着图层数量的增加,仍无法满足实时或近实时查询效果。 面向网格的空间数据管理方式,能够很好地解决这个问题。本文详细说明其使用过程。

基本原理

该使用场景的基本原理:对原始数据的各图层对象进行编码,保留对象ID和网格,汇总到一张网格编码表,示例如下:

geosot-grids-schema

查询过程: 1. 计算对象压盖的网格,层级必须与被查询列的网格层级一致; 2. 计算出的网格数组与网格编码表的网格数组列进行求交,有相同网格的行被命中; 3. 命中的行再与原始数据做ID关联。

脚本及过程说明

-- 1. 创建网格编码表格 tb_geogrid
------1.1  创建自增序列对象
CREATE SEQUENCE public.tb_geogrid_id_seq INCREMENT BY 1  MINVALUE 1 MAXVALUE 2147483647 START 1 CACHE 1 NO CYCLE;
------1.2  创建表格 tb_geogrid,编码值将存储在 grids_level_15 列
CREATE TABLE public.tb_geogrid (id int4 NOT NULL DEFAULT nextval('tb_geogrid_id_seq'::regclass), tablename text NULL,
    smid int8 NULL, grids_level_15 _geosotgrid NULL);

-- 2. 各图层对象编码计算并数据写入tb_geogrid表的grids_level_15列,15层编码;图层名以 xxx 示意
------ 注意: st_geosotgrid(smgeometry, 15) 中,smgeometry 是否带Z值,决定了生成的网格是否带Z值;同一列中的网格必须具有相同层级和Z方向标记
insert into tb_geogrid(tablename, smid, grids_level_15 ) (select 'xxx', smid ,st_geosotgrid(smgeometry, 15) from xxx);

-- 3. 为 geogrid表 的 grids_level_15 列创建gin索引
CREATE INDEX idx_tb_geogrid_grids ON public.geogrid USING gin (grids_level_15);

-- 4. 查询过滤
select tablename,count(*) from tb_geogrid  where grids_level_15 && st_geosotgrid(ST_MakeEnvelope(116.4, 40, 116.45, 40.05, 4490), 22) group by tablename;

本例提供的基于网格编码的多图层穿越查询方法,不影响原始数据,提供高效检索性能的同时,也适用于对只读的存量数据管理。