我正在将SQLite数据库 struct 迁移到PostgreSQL.该SQLite数据库使用带有空间索引的R*Tree模块进行快速3D边界框搜索.

我没有使用空间索引和PostgreSQL的经验.

我已经阅读了有关PostgreSQL Gist索引的文档,这似乎表明这可以实现类似的功能.不过,我一直无法找到如何将此功能应用于3D边界框判断.

我想,带框和点的<@运算符应该能起到作用.谁能详细说明这种直觉是否正确,并提供一个小示例,说明如何定义具有空间3D数据的表和执行边界框判断的查询?

下面是我正在寻找的示例数据和查询思想:

id x y z
1 0 1 2
2 4 5 6

SELECT id FROM table WHERE x >= 0 AND x <= 2 AND y >= 0 AND y <= 2 AND z >= 0 AND z <= 2

推荐答案

对于PostGIS,您可以设置一个高达4D的基于R-Tree的索引作为任何其他GIST索引.Demo at db<>fiddle:

设置包含示例的表格:

create extension postgis;

create table business(
  id int generated by default as identity primary key,
  business_name text,
  x numeric, y numeric, z numeric, t numeric,
  geom geometry(PointZM,4326) generated always as 
      (st_setsrid(st_makepoint(x,y,z,t),4326)) stored);

select setseed(.4);
insert into business (business_name,x,y,z,t)
select 'business_'||n, x, y, z, t
from generate_series(1,1e5,1)a(n),
  lateral(select   n AS n1,
                   180-random()*360 x,
                   90 -random()*180 y, 
                   50 -random()*100 z,
                   50 -random()*100 t)b;

设置索引.默认运算符类将仅使用每个几何图形的两个维度来构建r-树,因此您需要指定gist_geometry_ops_nd个运算符类来处理n维几何图形的所有维度:

create index geom_idx on business using gist(geom gist_geometry_ops_nd);

一种测试操作,显示索引用途: Select 最接近参考点的7个点:

prepare postgis_based as
select id,business_name,x,y,z,t
      ,(select geom from business where id=42)<<->>geom AS distance 
from business
order by distance
limit 7;

explain analyze execute postgis_based;
execute postgis_based;
QUERY PLAN
Limit  (cost=8.59..9.53 rows=7 width=73) (actual time=0.428..1.624 rows=7 loops=1)
  InitPlan 1 (returns $0)
    ->  Index Scan using business_pkey on business business_1  (cost=0.29..8.31 rows=1 width=48) (actual time=0.008..0.008 rows=1 loops=1)
          Index Cond: (id = 42)
  ->  Index Scan using geom_idx on business  (cost=0.28..13468.38 rows=100005 width=73) (actual time=0.427..1.622 rows=7 loops=1)
        Order By: (geom <<->> $0)
Planning Time: 0.351 ms
Execution Time: 1.689 ms
id business_name x y z t distance
42 business_42 -91.8261216469166 7.7997970642875 2.93153014852416 13.8754985934873 0
39781 business_39781 -91.651074810554 10.1567444370512 1.08794511732091 19.9058199716022 6.734198096546056
10212 business_10212 -96.0308356409243 6.16780328827525 6.99214194619289 17.9070448007494 7.285942385786669
78354 business_78354 -94.2913320527778 12.8802423990292 5.95771554931872 17.565112372697 7.393188423419308
82772 business_82772 -90.3963886636943 13.9114309111029 -2.37759157752899 15.9845495479146 8.487112236283533
47097 business_47097 -93.041286078567 14.2177864450063 -1.89386518525991 11.233109282625 8.540133118659915
94516 business_94516 -87.3058458168426 1.38796268779309 1.78446589911467 18.3034143744421 9.08111822448362

如果在使用默认索引设置时将xy置零,而只填充zt,则可以为observe slow sequential scans kicking in,这表示只使用了前两个维度来构建树,因此在该场景中没有帮助.一旦你切换到gist_geometry_ops_nd,你就开始得到quick index scans.

Postgresql相关问答推荐

PostgreSQL:如何 for each 唯一的客户输入/更新列中的数据,并将其递增1直到表的末尾

ANTLR4 PostgreSQL语法被 destruct 了吗?

为什么32632投影中的几何图形并不完美?

如何在Postgres中对分区表使用Hibernate验证?

PostgreSQL 中的 Datum 数据类型是什么以及它的用途是什么?

如何使用 PostgreSQL 数据库中的函数和存储过程从动态表中获取所有数据?参数传入的表名

postgres 如何计算多列哈希?

如何使用有限的varchar在postgres中存储单词é

在 jOOQ 中 Select 相同的命名列

Postgres内部如何计算月份间隔

如何在 postgresql 上使用 sqlalchemy 进行正确的 upsert?

如何在 psycopg2 中使用服务器端游标

SQL:当谈到 NOT IN 和 NOT EQUAL TO 时,哪个更有效,为什么?

错误:syntax error at or near "user"

需要将整个 postgreSQL 数据库加载到 RAM 中

从 psycopg2 异常中获取错误消息

从局域网访问 PostgreSQL 服务器

安装了 Postgres.app 但它不起作用

如何在Postgres中分组并返回总和行

重命名 Amazon RDS 主用户名