我已经使用Postgis 2.0一年了3/4,虽然我真的很喜欢使用它,但是查询处理时间过长,使得它基本上无法用于我的用例。通常包含数十万个多边形的市政数据集。这些多面体的形状有时会非常不规则,每个多角形的范围从4点到78,000点不等。以下统计的总耗时:

ArcGIS 10.0 (on same host with windows 7 OS): 3 minutes
Postgis:56 minutes (not including geometry pre-processing queries)


换句话说,在Postgis中完成此交集所需的时间比在ArcGIS中多1500%,这是我的查询更简单!

ArcGIS据说运行速度更快的原因之一是由于索引更好。一些程序员最近弄清楚了这些索引是如何工作的,我想知道是否有人知道如何在Postgis中构建这些索引(或构建可以模拟索引的表)。也许这可以解决Postgis中的大多数速度问题。我只能希望必须有某种方法,特别是因为ArcGIS只能使用4 GB的RAM,而我的Postgis服务器最多可以使用4倍的RAM!运行缓慢,因此我将提供系统规格的详细版本:

Machine: Dell XPS 8300 
Processor: i7-2600 CPU @ 3.40 GHz 3.40 GHz 
Memory: Total Memory 16.0 GB (10.0 GB on virtual machine)

Platform: Ubuntu Server 12.04 Virtual Box VM

Potgres Version: 9.1.4
Postgis Version: POSTGIS="2.0.1 r9979" GEOS="3.3.5-CAPI-1.7.5" PROJ="Rel. 4.8.0, 6 March 2012" GDAL="GDAL 1.9.1, released 2012/05/15" LIBXML="2.7.8" LIBJSON="UNKNOWN" TOPOLOGY RASTER


我还详细介绍了我用于设置Postgis的整个安装过程,包括创建

我还将conf文件中的共享内存从默认的24MB增加到了6 GB,并运行以下命令以允许postgres运行:

sudo sysctl -w kernel.shmmax=7516192768 (I know this setting is deleted every time you restart the OS)
sudo /etc/init.d/postgresql restart


据我所知,在性能方面绝对没有任何明显的变化。
包裹:tcad_parcels_06142012.shp.zip,来自德克萨斯州奥斯丁市

辖区:德克萨斯州奥斯丁市的辖区


这里是我处理数据的步骤:

ArcGIS


将数据集添加到ArcMap
将坐标系设置为中部得克萨斯英尺(srid 2277)
从下拉菜单中使用交点工具

Postgis

使用以下项导入宗地:

shp2pgsql -c -s 2277 -D -i -I -W UTF-8 "tcad_parcels_06142012.shp" "public"."tcad_parcels_06142012" |psql -d postgis_testing -U postgres -h local_ip -p 5432


使用以下各项导入管辖区:

shp2pgsql -c -s 2277 -D -i -I -W UTF-8 "jurisdictions.shp" "public"."jurisdictions" |psql -d postgis_testing -U postgres -h local_ip -p 5432


清理宗地中的无效几何图形:

DROP TABLE IF EXISTS valid_parcels;
CREATE TABLE valid_parcels(
  gid serial PRIMARY KEY,
  orig_gid integer,
  geom geometry(multipolygon,2277)
);
CREATE INDEX ON valid_parcels USING gist (geom);
INSERT INTO valid_parcels(orig_gid,geom)
  SELECT 
    gid 
    orig_gid,
    st_multi(st_makevalid(geom)) 
  FROM 
    tcad_parcels_06142012;
CLUSTER valid_parcels USING valid_parcels_geom_idx;


在管辖区域中清理无效的几何图形:

DROP TABLE IF EXISTS valid_jurisdictions;
CREATE TABLE valid_jurisdictions(
  gid serial PRIMARY KEY,
  orig_gid integer,
  geom geometry(multipolygon,2277)
);
CREATE INDEX ON valid_jurisdictions USING gist (geom);
INSERT INTO valid_jurisdictions(orig_gid,geom)
  SELECT 
    gid 
    orig_gid,
    st_multi(st_makevalid(geom)) 
  FROM 
    jurisdictions;
CLUSTER valid_jurisdictions USING valid_jurisdictions_geom_idx;


运行群集:

运行真空分析:

cluster;


在已清洗的桌子上进行交点:

vacuum analyze;


/>解释交叉路口查询:

CREATE TABLE parcel_jurisdictions(
  gid serial primary key,
  parcel_gid integer,
  jurisdiction_gid integer,
  isect_geom geometry(multipolygon,2277)
);
CREATE INDEX ON parcel_jurisdictions using gist (isect_geom);

INSERT INTO parcel_jurisdictions(parcel_gid,jurisdiction_gid,isect_geom)
  SELECT
    a.orig_gid parcel_gid,
    b.orig_gid jurisdiction_gid,
    st_multi(st_intersection(a.geom,b.geom))
  FROM
    valid_parcels a, valid_jurisdictions b
  WHERE
    st_intersects(a.geom,b.geom);


从我阅读的所有内容中,我的交叉路口查询都是高效的,而且我完全不知道我在做什么错在干净的几何体上花费56分钟!

评论

在PostGIS中,添加边界框交叉检查以加快处理速度是常见的习惯。尝试在您的WHERE子句中添加“ AND a.geom && b.geom”,看看它有什么不同。

st_intersects()包含边界框查询,然后在postgis 2.x中执行任何交集测试,因此很遗憾,这样不会节省任何时间。

您可以使用EXPLAIN ANALYZE运行查询并发布结果吗?

您还应该注意,您在postgis和arcgis上运行的数据集不同,因为您说要让neex使它们有效以被vy postgis接受。

是否可以获取数据集进行查看?

#1 楼

不同的方法。知道痛苦在ST_Intersection中,并且对/错测试很快,尝试最小化通过相交的几何体数量可能会加快速度。例如,不需要修剪完全包含在辖区中的宗地,但是ST_Intersection可能仍会麻烦一些,那就是在构建交集叠加层的一部分之前,不必意识到它不需要生成任何新的几何图形。因此,此

INSERT INTO parcel_jurisdictions(parcel_gid,jurisdiction_gid,isect_geom)
SELECT
  a.orig_gid AS parcel_gid,
  b.orig_gid AS jurisdiction_gid,

  st_multi(st_intersection(a.geom,b.geom)) AS geom
FROM
  valid_parcels a, valid_jurisdictions b
WHERE
  st_intersects(a.geom, b.geom) and not st_within(a.geom, b.geom)
UNION ALL
SELECT
  a.orig_gid AS parcel_gid,
  b.orig_gid AS jurisdiction_gid,
  a.geom AS geom
FROM
  valid_parcels a, valid_jurisdictions b
WHERE
  st_within(a.geom, b.geom);


甚至更短

INSERT INTO parcel_jurisdictions(parcel_gid,jurisdiction_gid,isect_geom)
SELECT
  a.orig_gid AS parcel_gid,
  b.orig_gid AS jurisdiction_gid,
  CASE 
     WHEN ST_Within(a.geom,b.geom) 
     THEN a.geom
     ELSE ST_Multi(ST_Intersection(a.geom,b.geom)) 
  END AS geom
FROM valid_parcels a
JOIN valid_jurisdictions b
ON ST_Intersects(a.geom, b.geom)


甚至在没有UNION的情况下甚至可能更快。 br />

评论


谢谢,使我下降到3.63分钟!我从未想到过工会会更快。这个答案真的会让我重新思考从现在开始我进行查询的方式。

– THX1138
2012年8月16日在6:22

这很酷。我在工作的情况下,我的st_intersection查询要花30分钟以上的时间,现在我知道如何避免这种情况了:)

–内森·W
2012年8月16日上午8:14

这个问题使我学习了Postgis!我今天会睡个好觉,看到Postgis与Arcgis并肩作战:-)

– Vinayan
2012年8月16日15:42



马丁·戴维斯(Martin Davis)的另一项改进,您可以内联“进出”?使用CASE语句向SELECT提问,并避免使用UNION。

– Paul Ramsey
2012年8月20日在18:54

UNION从两个查询中消除了重复的行,但是这两个查询的结果集中不能有相同的行。因此,跳过重复检查的UNION ALL在这里比较合适。 (我并没有那么多地使用UNION,但是通常我发现我经常使用UNION ALL。)

– jpmc26
16-10-21在19:08



#2 楼

如果您省略"st_multi(st_intersection(a.geom,b.geom))"部分,会发生什么?我将其用于您提供的数据。

INSERT INTO parcel_jurisdictions(parcel_gid,jurisdiction_gid,isect_geom)
  SELECT
    a.orig_gid parcel_gid,
    b.orig_gid jurisdiction_gid,
    a.geom
  FROM
    valid_parcels a, valid_jurisdictions b
  WHERE
    st_intersects(a.geom,b.geom);


配置

Processor: AMD Athlon II X4 635 2.9 GHz 
Memory: 4 GB
Platform: Windows 7 Professional
Potgres Version: 8.4
Postgis Version: "POSTGIS="2.0.1 r9979" GEOS="3.3.5-CAPI-1.7.5" PROJ="Rel. 4.8.0, 6 March 2012" GDAL="GDAL 1.9.1, released 2012/05/15" LIBXML="2.7.8" LIBJSON="UNKNOWN" TOPOLOGY RASTER"


分析结果

"Nested Loop  (cost=0.00..7505.18 rows=217489 width=1580) (actual time=1.994..248405.616 rows=329150 loops=1)"
"  Join Filter: _st_intersects(a.geom, b.geom)"
"  ->  Seq Scan on valid_jurisdictions b  (cost=0.00..37.25 rows=525 width=22621) (actual time=0.054..1.732 rows=525 loops=1)"
"  ->  Index Scan using valid_parcels_index on valid_parcels a  (cost=0.00..11.63 rows=2 width=1576) (actual time=0.068..6.423 rows=1366 loops=525)"
"        Index Cond: (a.geom && b.geom)"
"Total runtime: 280087.497 ms"


评论


不,他想要合成的相交多边形,但是您的查询很好地证明了所有的麻烦都在于相交生成,而不是查询的二进制true / false测试部分。这是完全可以预期的,因为对真/假代码进行了高度优化,而对交集生成却没有进行优化。

– Paul Ramsey
2012年8月15日在20:28