2つの空間テーブル間の交差を改善するのに苦労しており、テーブルのデザイン、クエリ、または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
毎回1つの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行をループして、それぞれの交差と面積を直接取得するストアドプロシージャを作成することを考えています。それは良い考えですか?
サーバーは他のデータベース間で共有されていますが、クエリを実行すると同時に重いプロセスが並行して実行されていませんでした。
ほぼ100kの頂点を持つ非常に複雑な特定の機能があります。 Postgresのバージョンについては、DBAだけがインフラストラクチャを更新でき、私はそれらの1人ではありません。
これが公開されて以来、問題は進化し、現在は140kk +行を処理しています。ただし、Postgisも進化し、機能テーブルを「修正」できるようになりました。 ArcMapからDice
を使用する必要はもうありません。
ST_VoronoiPolygons アプローチを使用してそれを行いました。元のテーブルの機能を処理可能なサイズに分割する関数を使用して、機能する Gist を作成しました。
詳細については、他のツールを使用してこれを行うことができ、ワークロードを分割しました。
このプロセスが完了するまでに3時間ほどかかります。
ST_Intersects
は軽いです。問題はこの計算でした:
st_area(st_intersection(grade.the_geom, uso.geom)).
複雑なフィーチャの交差部分を作成し、面積を計算するのは困難な作業でした。