web-dev-qa-db-ja.com

2つの巨大な空間テーブル間のIntersectクエリの最適化

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時間実行されましたが、実行をキャンセルすることにしたときは何も結果がありませんでした。サブサンプルでこれだけ時間がかかった場合は、完全なデータセットで想像してみてください。

両方のテーブルは以前に真空分析されました。

遅いクエリの場合はEXPLAINhttp://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_2012teste2.uso_2012は、uso_2012の列が1つ少ない場合とほとんど同じです。

ご覧のとおり、これはあまり有望ではありません。このプロセスをスピードアップするための推奨事項はありますか?

177,888行をループして、それぞれの交差と面積を直接取得するストアドプロシージャを作成することを考えています。それは良い考えですか?

構成:

  • shared_buffers:1920 MB
  • work_memory:36 MB
  • effective_cache_size:5632 MB

サーバー情報:

  • PostgreSQL 9.2.14
  • CENTOSリリース6.4
  • 8GB SRAM
  • ストレージV7000
  • INTEL(R)XEON(R)CPU E5-2620 2 GHZ
  • POSTGIS = "2.0.2 r10789" GEOS = "3.3.6-CAPI-1.7.6" PROJ = "Rel。4.8.0、6 March 2012" GDAL = "GDAL 1.9.2、release 2012/10/08" LIBXML = "2.7.6"ラスター

サーバーは他のデータベース間で共有されていますが、クエリを実行すると同時に重いプロセスが並行して実行されていませんでした。

ほぼ100kの頂点を持つ非常に複雑な特定の機能があります。 Postgresのバージョンについては、DBAだけがインフラストラクチャを更新でき、私はそれらの1人ではありません。

5
Diego Felipe

更新:

これが公開されて以来、問題は進化し、現在は140kk +行を処理しています。ただし、Postgisも進化し、機能テーブルを「修正」できるようになりました。 ArcMapからDiceを使用する必要はもうありません。

ST_VoronoiPolygons アプローチを使用してそれを行いました。元のテーブルの機能を処理可能なサイズに分割する関数を使用して、機能する Gist を作成しました。

元の回答:

詳細については、他のツールを使用してこれを行うことができ、ワークロードを分割しました。

  • すべてがうまく機能するように、私は各機能を最大800頂点および最大15km²に制限する必要がありました。私はいくつかのツールを試しましたが、plsqlで繰り返し手順を試しましたが、成功しませんでした。すべてを正しく試し、分割した唯一のものは、ArcMapの Dice 機能でした。
  • 170k行以上を20行のチャンクに分割し、クエリの6つのインスタンスを並列で実行して、.netコンソールアプリを使用して面積を計算しました。
  • 領域が保存されているので、チャンクと並列でいくつかの処理を実行し、各9kk +セルの値を計算することができました。

このプロセスが完了するまでに3時間ほどかかります。


ST_Intersectsは軽いです。問題はこの計算でした:

st_area(st_intersection(grade.the_geom, uso.geom)).

複雑なフィーチャの交差部分を作成し、面積を計算するのは困難な作業でした。

2
Diego Felipe