ฉันใช้ Postgis 2.0 เป็นเวลา 3/4 ของปีแล้วและในขณะที่ฉันสนุกกับการใช้งานจริง ๆ เวลาที่ใช้ในการประมวลผลแบบสอบถามที่มากเกินไปทำให้มันใช้ไม่ได้กับกรณีการใช้งานของฉัน
ฉันมักจะทำการประมวลผลทางภูมิศาสตร์อย่างหนักในชุดข้อมูลเทศบาลซึ่งมักจะมีหลายหมื่นหลายพัน รูปหลายเหลี่ยมเหล่านี้บางครั้งมีรูปร่างที่ผิดปกติมากและอาจแตกต่างกันจาก 4 คะแนนเป็น 78,000 จุดต่อหลายรูปหลายเหลี่ยม
ตัวอย่างเช่นเมื่อฉันตัดชุดข้อมูลพัสดุภัณฑ์ด้วยชุดข้อมูลจำนวน 329,152 ชุดโดยมีชุดเขตอำนาจศาลที่ประกอบด้วยชุดข้อมูลจำนวน 525 ชุดฉันจะได้รับสถิติต่อไปนี้สำหรับเวลาทั้งหมดที่ใช้ไป:
ArcGIS 10.0 (on same host with windows 7 OS): 3 minutes
Postgis:56 minutes (not including geometry pre-processing queries)
กล่าวอีกนัยหนึ่งมันต้องใช้เวลาในการทำจุดตัดนี้ใน Postgis มากกว่า 1500% กว่าใน ArcGIS - และนี่คือหนึ่งในข้อความค้นหาที่เรียบง่ายของฉัน!
เหตุผลหนึ่งที่ ArcGIS คาดว่าจะทำงานได้เร็วกว่านั้นก็เนื่องมาจากดัชนีที่ดีขึ้น โปรแกรมเมอร์บางคนเพิ่งรู้ว่าดัชนีเหล่านี้ทำงานอย่างไรและฉันสงสัยว่าใครรู้วิธีสร้างดัชนีเหล่านี้ใน Postgis (หรือสร้างตารางที่จะเลียนแบบดัชนี) บางทีนี่อาจช่วยแก้ปัญหาความเร็วส่วนใหญ่ใน Postgis ฉันหวังว่าคงมีบางทางเท่านั้นโดยเฉพาะอย่างยิ่งเนื่องจาก ArcGIS สามารถใช้ RAM ได้ 4 GB ในขณะที่ฉันสามารถใช้งานได้มากถึง 4 เท่าสำหรับเซิร์ฟเวอร์ postgis ของฉัน!
แน่นอนมีหลายเหตุผลที่ postgis สามารถทำงานได้ช้าดังนั้นฉันจะให้รายละเอียดรุ่นของระบบของฉัน:
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 รวมถึงการสร้างของ VM ตัวเอง
ฉันยังเพิ่มหน่วยความจำที่แชร์จาก 24MB เริ่มต้นเป็น 6 GB ในไฟล์ conf และรันคำสั่งต่อไปนี้เพื่ออนุญาตให้ 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
เท่าที่ฉันสามารถบอกได้ว่าสิ่งนี้ไม่ได้สังเกตเห็นอะไรเลยในแง่ของประสิทธิภาพ
นี่คือลิงค์ไปยังข้อมูลที่ฉันใช้สำหรับการทดสอบนี้:
- Parcels: tcad_parcels_06142012.shp.zipจากเมือง Austin, TX
- เขตอำนาจศาล: เขตแดนจากเมือง Austin, TX
นี่คือขั้นตอนที่ฉันใช้ในการประมวลผลข้อมูล:
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);
อธิบายวิเคราะห์คำแยกกัน:
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)
จากทุกสิ่งที่ฉันได้อ่านแบบสอบถามทางแยกของฉันมีประสิทธิภาพและฉันไม่รู้ว่าสิ่งที่ฉันทำผิดสำหรับการค้นหาใช้เวลา 56 นาทีในรูปทรงเรขาคณิตที่สะอาด!