优化两个巨大空间表之间的 Intersect 查询

Die*_*ipe 5 postgresql performance spatial postgis query-performance

我在尝试改进两个空间表之间的交集时遇到了困难,我想收到有关表设计、查询或 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);
Run Code Online (Sandbox Code Playgroud)

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);
Run Code Online (Sandbox Code Playgroud)

问题:

我想要的只是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
Run Code Online (Sandbox Code Playgroud)

然而,当我决定取消它的执行时,这个查询运行了大约16 个小时没有任何结果。如果子样本花了这么长时间,想象一下完整的数据集。

两个表之前都进行了真空分析。

EXPLAIN对于慢查询:http : //explain.depesz.com/s/PEV

我认为gridcode每次在多个查询中将其分开可能是个好主意。这就是我创建哈希索引的原因。

这是teste2.uso_2012表中的数据分布:

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);
Run Code Online (Sandbox Code Playgroud)

以下是个人的一些查询结果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
Run Code Online (Sandbox Code Playgroud)

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" 光栅

服务器在其他数据库之间共享,但在我运行查询的同时没有并行运行繁重的进程。

我有一些非常复杂的特殊功能,几乎有 10 万个顶点。关于 Postgres 版本,只有 DBA 可以更新基础设施,而我不是其中之一。

Die*_*ipe 2

更新:

\n\n

自本文发布以来,问题不断发展,现在我们处理 140kk+ 行。然而,Postgis 也在不断发展,现在可以“修复”特征表。不再需要DiceArcMap。

\n\n

我使用ST_VoronoiPolygons方法完成此操作。我创建了一个工作要点,其中包含一个函数,该函数可以将原始表上的特征分解为可行的大小以进行处理。

\n\n

原答案:

\n\n

有关信息,我可以使用其他工具并分配工作量来完成此操作:

\n\n
    \n
  • 为了一切正常,我必须将每个特征限制在 800 个顶点 \nmax 和 15 km\xc2\xb2 最大值。我尝试了一些工具,甚至是非 plsql 的重复过程,但没有成功。我唯一尝试并正确分割的就是ArcMap 的Dice功能;
  • \n
  • 我将 17 万多行分成 20 行块,并并行运行 6 个查询实例,以使用 .net 控制台应用程序计算面积;
  • \n
  • 通过存储的区域,我能够进行一些处理,也可以在块和并行中进行,以计算每个 9kk+ 单元格的值。
  • \n
\n\n

现在,此过程“仅”需要 3 个小时即可完成。

\n\n
\n\n

ST_Intersects轻。问题是这个计算:

\n\n
st_area(st_intersection(grade.the_geom, uso.geom)).\n
Run Code Online (Sandbox Code Playgroud)\n\n

构建复杂特征的交集并计算面积是一项艰巨的任务。

\n