Я використовую 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 може використовувати лише 4 ГБ оперативної пам’яті, тоді як я міг використовувати до 4 разів більше, ніж для свого 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
Я також детально розповідаю про весь процес встановлення, який я використовував для налаштування постгігів, включаючи створення самого VM .
Я також збільшив спільну пам'ять з 24 Мб за замовчуванням до 6 ГБ у файлі conf та запустив наступні команди, щоб дозволити запускати поштові записи:
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)
- Скористайтеся інструментом перетину зі спадного меню
Постгіс
Імпорт посилок за допомогою:
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 хвилин чистої геометрії!