.. _demogeosot2_label: 基于GeoSOT编码的多图层穿越查询 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 在海量空间数据管理系统中,经常用到多图层查询的应用,比如查看指定范围内有哪些图层,各图层在此区域大约有多少对象并获取属性相关的统计数据。 传统的实现方式,是对所有图层进行范围过滤,尽管有各图层有空间索引进行加速,随着图层数量的增加,仍无法满足实时或近实时查询效果。 面向网格的空间数据管理方式,能够很好地解决这个问题。本文详细说明其使用过程。 基本原理 -------------------- 该使用场景的基本原理:对原始数据的各图层对象进行编码,保留对象ID和网格,汇总到一张网格编码表,示例如下: |geosot-grids-schema| 查询过程: 1. 计算对象压盖的网格,层级必须与被查询列的网格层级一致; 2. 计算出的网格数组与网格编码表的网格数组列进行求交,有相同网格的行被命中; 3. 命中的行再与原始数据做ID关联。 脚本及过程说明 --------------------- .. code:: sql -- 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; 本例提供的基于网格编码的多图层穿越查询方法,不影响原始数据,提供高效检索性能的同时,也适用于对只读的存量数据管理。 .. |geosot-grids-schema| image:: /../_static/images/demo_geosot/5.geosot2-grids-schema.png :width: 600px