【问题标题】:Optimizing a postgis query - why is 2nd index not being used?优化 postgis 查询 - 为什么不使用第二个索引?
【发布时间】:2021-05-23 22:01:26
【问题描述】:

我们有一个包含数千万个多边形的表格,我们有这个索引:

CREATE INDEX IF NOT EXISTS polygons_geog_idx ON polygons USING GIST(geog);

这让我们可以真正高效地查询数据库,如下所示:

SELECT * FROM polygons WHERE st_dwithin('SRID=4326;POINT(-1 50)'::geography, geog, 500);

现在由于业务需求,我们只需要返回最大的 200 个多边形。很容易做到:

  • LIMIT 200
  • ORDER BY st_area(geog)

完整查询: SELECT gid, st_area(geog) as size FROM polygons WHERE st_dwithin(geog, 'SRID=4326;POINT(-1 50)'::geography, 500) ORDER BY st_area(geog) DESC LIMIT 200.

由于 order byselect 我们的查询速度减慢了 10 倍。我认为通过添加另一个索引(如SO AnswerCREATE INDEX polygons_geog_area_idx ON polygons (st_area(geog));

但是polygons_geog_area_idx好像没有被接:

Sort  (cost=8.23..8.23 rows=1 width=12) (actual time=133.755..142.427 rows=2325 loops=1)
  Sort Key: (st_area(geog, true))
  Sort Method: quicksort  Memory: 205kB
  ->  Index Scan using polygons_geog_idx on polygons  (cost=0.14..8.22 rows=1 width=12) (actual time=0.468..121.974 rows=2325 loops=1)
        Index Cond: (geog && '0101000020E6100000C33126587787F1BF3B0D62B197654940'::geography)
        Filter: (('0101000020E6100000C33126587787F1BF3B0D62B197654940'::geography && _st_expand(geog, '500'::double precision)) AND _st_dwithin(geog, '0101000020E6100000C33126587787F1BF3B0D62B197654940'::geography, '500'::double precision, true))
        Rows Removed by Filter: 3
Planning Time: 0.157 ms
Execution Time: 151.196 ms

(注意:这是在开发数据集上,比稍后运行的实际数据集要小得多)

我错过了什么?你甚至可以使用我想要的 2 个索引吗?

【问题讨论】:

  • 请同时显示更快的计划。
  • @jjanes 更快的计划是什么意思?
  • 没有顺序的那个要快 10 倍。 (但如果生成的列确实有效,它可能就不再重要了)
  • 它确实有效@jjanes。谢谢你。我只是好奇为什么。

标签: postgresql performance indexing postgis


【解决方案1】:

PostgreSQL 不能以这种方式组合两个索引,一个用于顺序,一个用于选择性。

为了按面积排序,首先需要计算面积。排序本身很快(只占用 15% 的时间),所以一定是区域的计算速度很慢。 EXPLAIN VERBOSE 向我建议,该区域的计算是作为索引扫描的一部分完成的,然后将结果传递给排序,而不是在排序本身中完成。因此,将执行此操作的时间归因于索引扫描是有道理的。

为了缩短计算面积所需的时间,您可以将其计算并存储为表格的一部分。最好的方法(使用足够新的版本)是使用生成的列。

alter table polygons add polygon_area double precision generated always as (st_area(geog)) stored;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-09
    • 1970-01-01
    • 2015-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多