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分钟!
#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
评论
在PostGIS中,添加边界框交叉检查以加快处理速度是常见的习惯。尝试在您的WHERE子句中添加“ AND a.geom && b.geom”,看看它有什么不同。st_intersects()包含边界框查询,然后在postgis 2.x中执行任何交集测试,因此很遗憾,这样不会节省任何时间。
您可以使用EXPLAIN ANALYZE运行查询并发布结果吗?
您还应该注意,您在postgis和arcgis上运行的数据集不同,因为您说要让neex使它们有效以被vy postgis接受。
是否可以获取数据集进行查看?