【问题标题】:Postgis ST_Intersects between two tables really (really really) slow两个表之间的 Postgis ST_Intersects 真的(真的)很慢
【发布时间】:2019-07-01 13:08:21
【问题描述】:

我正在尝试在两个表之间进行空间连接:

  1. 表 1:397265 个特征(geom 字段上有 gist 索引)
  2. 表 2:73 个特征(geom 字段上有 gist 索引)

表 1 和表 2 具有相同的 SRID。

我做了很多测试,这些表之间的空间连接需要几天时间(5 天后我终止了查询)。我试图理解为什么解释分析这么慢:

EXPLAIN ANALYZE 
SELECT 
    table1.id,  table2.id
FROM table1
INNER JOIN table2 ON ST_Intersects(
        ST_Buffer(table1.geom,0),
        ST_Buffer(table2.geom,0)
)

但现在我仍在等待结果,因为 EXPLAIN ANALYZE 确实执行了查询。

如果我在这里只做一个解释就是结果:

"Gather  (cost=1000.00..3820127.08 rows=9667 width=40)"
"  Workers Planned: 3"
"  ->  Nested Loop  (cost=0.00..3818111.26 rows=3118 width=40)"
"        Join Filter: ((st_buffer(table2.geom, '0'::double precision) && st_buffer(table1.geom, '0'::double precision)) AND _st_intersects(st_buffer(table2.geom, '0'::double precision), st_buffer(table1.geom, '0'::double precision)))"
"        ->  Parallel Seq Scan on table1  (cost=0.00..21964.50 rows=128150 width=344)"
"        ->  Seq Scan on table2  (cost=0.00..9.73 rows=73 width=714516)"

我还更新了有关我计算机配置的 postgresql 配置文件:

shared_buffers = 8GB
effective_cache_size = 24GB
maintenance_work_mem = 2GB
checkpoint_completion_target = 0.9
wal_buffers = 16MB
default_statistics_target = 100
random_page_cost = 4
effective_io_concurrency = 2
work_mem = 10485kB
min_wal_size = 1GB
max_wal_size = 2GB
max_worker_processes = 7
max_parallel_workers_per_gather = 4
max_parallel_workers = 7

你能告诉我它有多长吗?

【问题讨论】:

    标签: postgis


    【解决方案1】:

    不使用空间索引。

    您可以删除buffer 的东西(也许先修复您的几何形状..)

    INNER JOIN table2 ON ST_Intersects(table1.geom,table2.geom)
    

    或者您可以在缓冲的几何图形上创建索引

    CREATE INDEX geom_idx ON table1 USING gist (ST_Buffer(table1.geom,0));
    

    【讨论】:

      【解决方案2】:

      正如其他评论所暗示的,最好修复几何形状。我猜你使用零距离的缓冲区来重建无效的几何图形。所以,最好的办法是

      UPDATE table1 SET geom = st_buffer(geom,0);
      UPDATE table2 SET geom = st_buffer(geom,0);
      

      然后重新索引表(按几何重新构建其原始 gist 索引)

      此外,根据几何性质,索引可能效率低下。 索引本身基本上是每个几何图形(多边形或线性形状周围的矩形)的一组边界框,确定哪些矩形首先相交然后从成对中定义精确的几何相交会更快。但是,如果您的多边形太大,其中大多数矩形相交和/或形状太复杂,则可能会减慢连接速度。

      此外,您可能拥有大量点密度的数据,这也会减慢算法速度,并且可以在不严重损害结果的情况下将其删除,尤其是在这些数据在空间上不是很准确的情况下。例如,您可以尝试简化数据

      ALTER table1 ADD COLUMN geom_simplified geom(<your geom type and srid>);
      UPDATE table1 SET geom_simplified = st_snaptogrid(geom,<relevant rounding number depending on your srid and desired accuracy>);
      

      签出this

      【讨论】:

        【解决方案3】:

        感谢@jgh 的回答,您已经找到了问题所在。未使用该索引。 我永远不会找到它,因为对我来说很明显,即使使用缓冲区也使用了索引。

        我已尝试清理数据,但有很多错误。所以我决定使用你的解决方案(ST_Buffer() 上的索引)

        我的查询现在需要 14 小时。关于表 2 中的特征数量还有很多时间,但至少查询结束了......

        "Gather  (cost=1000.14..116847.28 rows=397265 width=8) (actual time=70.548..51214359.966 rows=415151 loops=1)"
        "  Workers Planned: 3"
        "  Workers Launched: 3"
        "  ->  Nested Loop Left Join  (cost=0.14..76120.78 rows=128150 width=8) (actual time=1312.989..51210248.284 rows=103788 loops=4)"
        "        ->  Parallel Seq Scan on table1  (cost=0.00..21964.50 rows=128150 width=338) (actual time=0.009..3485.290 rows=99316 loops=4)"
        "        ->  Index Scan using table2_idx_buffer on table2  (cost=0.14..0.41 rows=1 width=714516) (actual time=460.535..515.510 rows=0 loops=397265)"
        "              Index Cond: (st_buffer(table1.geom, '0'::double precision) && st_buffer(geom, '0'::double precision))"
        "              Filter: _st_intersects(st_buffer(table1.geom, '0'::double precision), st_buffer(geom, '0'::double precision))"
        "              Rows Removed by Filter: 3"
        "Planning time: 0.227 ms"
        "Execution time: 51214434.490 ms"
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-11-10
          • 2010-12-28
          • 2013-01-25
          • 1970-01-01
          • 2012-01-30
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多