Postgis 2.0'ı bir yılın 3/4'ü boyunca kullanıyorum ve gerçekten kullanmaktan zevk alırken, aşırı sorgu işlem süresi onu kullanım durumum için temelde kullanılamaz hale getirdi.
Sık sık yüz binlerce çoklu poligona sahip belediye veri kümeleri üzerinde ağır coğrafi işlemler yapmaya meyilliyim. Bu multipolygonlar bazen çok düzensiz şekillenir ve multipolygon başına 4 ile 78.000 puan arasında değişebilir.
Örneğin, bir parsel veri kümesini 329 çokgen içeren bir yargı veri kümesine sahip 329,152 çok köşeli küme ile kestiğimde, tüketilen toplam süre için aşağıdaki istatistikleri alıyorum:
ArcGIS 10.0 (on same host with windows 7 OS): 3 minutes
Postgis:56 minutes (not including geometry pre-processing queries)
Başka bir deyişle, Postgis'te bu kavşağı yapmak için ArcGIS'e göre% 1500 daha fazla zaman gerekir - ve bu benim en basit sorgularımdan biri!
ArcGIS'in sözde daha hızlı çalışmasının sebeplerinden biri, daha iyi endekslerden kaynaklanıyor. Bazı programcılar son zamanlarda bu endekslerin nasıl çalıştığını öğrendiler ve kimsenin bu endeksleri Postgis'te (veya endeksleri taklit edecek tablolar oluşturacaklarını) nasıl yapabileceğini bilip bilmediğini merak ediyorum. Belki de bu Postgis'teki hız sorunlarının çoğunu çözecektir. Umarım bir yolun olması gerektiğini umarım, özellikle de ArcGIS postgis sunucum için 4 kata kadar kullanabildiğimde sadece 4 GB RAM kullanabilir.
Tabii ki postgis'in yavaş çalışmasının birçok nedeni var, bu yüzden sistem şartnamemin ayrıntılı bir versiyonunu sunacağım:
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
Ayrıca conf dosyasını paylaşılan belleği varsayılan 24 MB'tan 6 GB'a çıkardım ve postgres'lerin çalışabilmesi için aşağıdaki komutları çalıştırdım:
sudo sysctl -w kernel.shmmax=7516192768 (I know this setting is deleted every time you restart the OS)
sudo /etc/init.d/postgresql restart
Söyleyebileceğim kadarıyla performans açısından kesinlikle farkedilir hiçbir şey yapmaz.
İşte bu test için kullandığım verilere bağlantılar:
- Koliler: tcad_parcels_06142012.shp.zip dan Austin City
- Yargı: Yargı Sınırları dan Austin City
Verileri işlemek için attığım adımlar:
ArcGIS
- ArcMap'e veri setleri ekle
- Koordinat sistemini merkezi texas feet'e ayarla (2277 no'lu srid)
- Açılır menüden kesişim aracını kullanın
PostGIS
Parselleri kullanarak içe aktar:
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
Yetki alanlarını kullanarak ithalat:
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
Parsellerdeki geçersiz geometrileri temizleyin:
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;
Yargı bölgelerinde geçersiz geometri temizleyin:
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;
Küme çalıştır:
cluster;
Vakum analizini çalıştırın:
vacuum analyze;
Temizlenmiş masalarda kesişme yapın:
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);
Kavşak sorgusu analizini açıklayın:
Total runtime: 3446860.731 ms
Index Cond: (geom && b.geom)
-> Index Scan using valid_parcels_geom_idx on valid_parcels a (cost=0.00..11.66 rows=2 width=1592) (actual time=0.030..4.596 rows=1366 loops=525)
-> Seq Scan on valid_jurisdictions b (cost=0.00..113.25 rows=525 width=22621) (actual time=0.009..0.755 rows=525 loops=1)
Nested Loop (cost=0.00..61428.74 rows=217501 width=24213) (actual time=2.625..3445946.889 rows=329152 loops=1)
Join Filter: _st_intersects(a.geom, b.geom)
Okuduğum her şeyden sonra, kesişim sorgum verimlidir ve sorgunun temiz geometri üzerinde 56 dakika sürmesi için neyi yanlış yaptığım hakkında hiçbir fikrim yok!