優化兩個巨大空間表之間的相交查詢
我很難嘗試改進兩個空間表之間的交叉點,我想收到有關表設計、查詢或 dba 配置的任何提示。
表:
teste.recorte_grade
表現在有 1,655,569 行,但這是為這個 900 萬行表的測試而製作的子樣本。CREATE TABLE teste.recorte_grade ( id integer NOT NULL DEFAULT nextval('teste."Recorte_grade_id_seq"'::regclass), id_gre character varying(21), indice_gre character varying(16), the_geom geometry(Polygon), CONSTRAINT "Recorte_grade_pkey" PRIMARY KEY (id) ) WITH ( OIDS=FALSE ); CREATE INDEX sidx_recorte_grade_geom ON teste.recorte_grade USING gist (the_geom);
表
teste2.uso_2012
有 177,888 行,這是它將擁有的所有數據。CREATE TABLE teste2.uso_2012 ( id integer NOT NULL, gridcode smallint NOT NULL, geom geometry(MultiPolygon) NOT NULL, CONSTRAINT pk_id_uso_2012 PRIMARY KEY (id) ) WITH ( OIDS=FALSE ); CREATE INDEX idx_hash_calsse_uso_2012_teste2 ON teste2.uso_2012 USING hash (gridcode); CREATE INDEX sidx_uso_2012_geom_teste2 ON teste2.uso_2012 USING gist (geom);
問題:
我想要的只是
gridcode
兩個表之間每個交集的區域和,基本上,這個查詢的結果:Select grade.id, uso.gridcode, , st_area(st_intersection(grade.the_geom, uso.geom)) from teste2.uso_2012 as uso inner join teste.recorte_grade as grade on ST_Intersects(grade.the_geom, uso.geom) = 't' order by grade.id
然而,當我決定取消它的執行時,這個查詢執行了大約**16 個小時,沒有任何結果。**如果子樣本花了這麼長時間,想像一下完整的數據集。
兩個表之前都進行了真空分析。
EXPLAIN
對於慢查詢:http ://explain.depesz.com/s/PEV
gridcode
我認為每次將其分成多個查詢可能是一個好主意。這就是我創建雜湊索引的原因。這是
teste2.uso_2012
表中的數據分佈:+----------+---------------+---------------+ | Gridcode | Polygon Count | Total Area | +----------+---------------+---------------+ | 1 | 4100 | 40360812499 | | 2 | 16992 | 516217687499 | | 3 | 22745 | 955870062499 | | 4 | 32243 | 802054562500 | | 5 | 4286 | 69461437500 | | 6 | 16081 | 3200491312500 | | 7 | 40704 | 447186874999 | | 8 | 1776 | 89474187499 | | 9 | 1894 | 41834437499 | | 10 | 15918 | 1765555312500 | | 11 | 5158 | 306742062499 | | 12 | 15715 | 274680250000 | | 14 | 275 | 5606687500 | +----------+---------------+---------------+
以下是個人的一些查詢結果
gridcodes
:Select grade.id, uso.gridcode, st_area(st_intersection(grade.the_geom, uso.geom)) from teste.recorte_2012 as uso inner join teste.recorte_grade as grade on ST_Intersects(grade.the_geom, uso.geom) = 't' where uso.gridcode = 1 --11 seconds --10,069 rows retrieved --http://explain.depesz.com/s/tZV1 Select grade.id, uso.gridcode, st_area(st_intersection(grade.the_geom, uso.geom)) from teste.recorte_2012 as uso inner join teste.recorte_grade as grade on ST_Intersects(grade.the_geom, uso.geom) = 't' where uso.gridcode = 2 --3275 seconds --200,682 rows retrieved Select grade.id, uso.gridcode, st_area(st_intersection(grade.the_geom, uso.geom)) from teste2.uso_2012 as uso inner join teste.recorte_grade as grade on ST_Intersects(grade.the_geom, uso.geom) = 't' where uso.gridcode = 2 --Total query runtime: 3333 seconds --200,682 rows retrieved. Select grade.id, uso.gridcode, st_area(st_intersection(grade.the_geom, uso.geom)) from teste.recorte_2012 as uso inner join teste.recorte_grade as grade on ST_Intersects(grade.the_geom, uso.geom) = 't' where uso.gridcode = 10 --5 hours without result
teste.recorte_2012
並且teste2.uso_2012
幾乎是同一張表,其中uso_2012
少了 1 列。如您所見,這似乎不太有希望。有什麼建議可以加快這個過程嗎?
我正在考慮創建一個儲存過程來循環 177,888 行並直接獲取每一個的交叉點和麵積。這是一個好主意嗎?
配置:
- 共享緩衝區:1920 MB
- 工作記憶體:36 MB
- 有效記憶體大小:5632 MB
伺服器資訊:
- PostgreSQL 9.2.14
- CENTOS 6.4 版
- 8GB SRAM
- 儲存 V7000
- 英特爾(R) 至強(R) CPU E5-2620 2 GHZ
- POSTGIS=“2.0.2 r10789” GEOS=“3.3.6-CAPI-1.7.6” PROJ=“Rel. 4.8.0,2012 年 3 月 6 日” GDAL=“GDAL 1.9.2,2012/10/08 發布” LIBXML =“2.7.6” 光柵
該伺服器在其他數據庫之間共享,但在我執行查詢的同時沒有並行執行繁重的程序。
我有一些非常複雜的特殊功能,幾乎有 100k 個頂點。關於 Postgres 版本,只有 DBA 可以更新基礎設施,我不是其中之一。
更新:
自從發布以來,問題不斷發展,現在我們處理了 140kk+ 行。然而,Postgis 也在發展,現在可以“修復”特徵表。不再需要
Dice
來自 ArcMap。我使用ST_VoronoiPolygons方法做到了。我創建了一個工作要點,其功能可以將原始表上的特徵分解為可行的大小以進行處理。
原答案:
有關資訊,我可以使用其他工具並拆分工作負載來做到這一點:
- 為了一切正常,我不得不將每個特徵限制在最大 800 個頂點和最大 15 平方公里內。我在plsql上嘗試了一些工具,甚至是一個重複的過程,但沒有成功。我唯一嚐試並正確拆分所有內容的是 ArcMap 的Dice功能;
- 我將我的 170k+ 行分成 20 行的塊,並並行執行 6 個查詢實例,以使用 .net 控制台應用程序計算區域;
- 使用儲存的區域,我能夠進行一些處理,也可以分塊和並行計算,以計算每個 9kk+ 單元格的值。
這個過程現在“只”需要 3 個小時來完成。
ST_Intersects
很輕。問題是這個計算:st_area(st_intersection(grade.the_geom, uso.geom)).
建構複雜特徵的交集併計算面積是一項艱鉅的任務。