postgresql - Postgres/PostGIS 上的 Gist 索引仍然很慢

标签 postgresql indexing geospatial postgis spatial-index

我不是 Postgres/GIS 学科的专家,我对大型几何数据库(超过 2000 万条记录)有疑问。首先,我的设置如下所示:

mmt=# select version();
-[ RECORD 1 ]-------------------------------------------------------------------------------------------------------------
version | PostgreSQL 13.2 (Debian 13.2-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit

mmt=# select PostGIS_Version();
-[ RECORD 1 ]---+--------------------------------------
postgis_version | 3.1 USE_GEOS=1 USE_PROJ=1 USE_STATS=1

我正在查询的表包含以下列:

mmt=# \d titles
                                              Table "public.titles"
        Column        |           Type           | Collation | Nullable |                 Default                 
----------------------+--------------------------+-----------+----------+-----------------------------------------
 ogc_fid              | integer                  |           | not null | nextval('titles_ogc_fid_seq'::regclass)
 wkb_geometry         | bytea                    |           |          | 
 timestamp            | timestamp with time zone |           |          | 
 end                  | timestamp with time zone |           |          | 
 gml_id               | character varying        |           |          | 
 validfrom            | character varying        |           |          | 
 beginlifespanversion | character varying        |           |          | 
 geom_bounding_box    | geometry(Geometry,4326)  |           |          | 
Indexes:
    "titles_pkey" PRIMARY KEY, btree (ogc_fid)
    "geom_idx" gist (geom_bounding_box)

geom_bounding_box 列包含 wkb_geometry 的边界框。我已经创建了那个边界框列,因为 wkb 几何形状超过了 GIST 索引中项目的默认大小限制。其中一些是非常复杂的几何形状,由几十个点组成一个多边形。使用边界框代替意味着我能够在该列上放置一个索引作为加速搜索的一种方式。至少理论上是这样。

我的搜索旨在找到落在给定点 100 米范围内的几何图形,如下所示,但这需要两分钟多的时间才能返回。我想在一秒钟内完成!:

select ogc_fid, web_geometry from titles where ST_DWithin(geom_bounding_box, 'SRID=4326;POINT(-0.145872 51.509691)'::geography, 100);

下面是一个基本的解释输出。我可以做些什么来加快这件事?

谢谢!

mmt=# explain select ogc_fid from titles where ST_DWithin(geom_bounding_box, 'SRID=4326;POINT(-0.145872 51.509691)'::geography, 100);
-[ RECORD 1 ]----------------------------------------------------------------------------------------------------------------------------------------------------------
QUERY PLAN | Gather  (cost=1000.00..243806855.33 rows=2307 width=4)
-[ RECORD 2 ]----------------------------------------------------------------------------------------------------------------------------------------------------------
QUERY PLAN |   Workers Planned: 2
-[ RECORD 3 ]----------------------------------------------------------------------------------------------------------------------------------------------------------
QUERY PLAN |   ->  Parallel Seq Scan on titles  (cost=0.00..243805624.63 rows=961 width=4)
-[ RECORD 4 ]----------------------------------------------------------------------------------------------------------------------------------------------------------
QUERY PLAN |         Filter: st_dwithin((geom_bounding_box)::geography, '0101000020E61000006878B306EFABC2BF6308008E3DC14940'::geography, '100'::double precision, true)
-[ RECORD 5 ]----------------------------------------------------------------------------------------------------------------------------------------------------------
QUERY PLAN | JIT:
-[ RECORD 6 ]----------------------------------------------------------------------------------------------------------------------------------------------------------
QUERY PLAN |   Functions: 4
-[ RECORD 7 ]----------------------------------------------------------------------------------------------------------------------------------------------------------
QUERY PLAN |   Options: Inlining true, Optimization true, Expressions true, Deforming true

最佳答案

问题是您正在混合使用 geometrygeography,而 PostgreSQL 将 geom_bounding_box 转换为 geography 以便他们匹配。

现在您已经索引了 geom_bounding_box,但没有索引 geom_bounding_box::geography,这是不同的。

要么使用 'SRID=4326;POINT(-0.145872 51.509691)'::geometry 作为第二个操作数,要么在 ((geom_bounding_box::geography)) 上创建 GiST 索引>(注意双括号)。

关于postgresql - Postgres/PostGIS 上的 Gist 索引仍然很慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67474739/

相关文章:

python - Numpy 数组索引与其他数组会产生广播错误

python - 使用 Selenium 查找 div 中的索引元素

elasticsearch - 寻找某人来帮助我使用ElasticSearch

json - 在 OpenLayers 中保存和恢复几何图形

SQL:何时以及为什么允许两个 on 条件?

c++ - 使用 PostgreSQL 时 SOCI 库中的高精度时间戳

PostgreSQL WITH RECURSIVE 查询通过分区键获取有序的父子链

ruby-on-rails - 迁移到 postgresql 时无法创建数据库

sql - 我应该添加主键列作为 Oracle RDBMS 中索引的最后一列吗?

python - 如何引发坐标超出栅格范围(rasterio.sample)的错误?